IHG Rooms API
Real-time room availability, cash rates, and IHG One Rewards points pricing for any property in the IHG portfolio — returned in a single response.
Overview
Two parallel pricings per room
Each room returns both rates[] (cash bookings, in the property's local currency) and reward_options[] (IHG One Rewards: points-only and points+cash combinations). Use whichever fits your application.
The IHG Rooms endpoint queries IHG's live availability service and returns every bookable room type at a property for the requested dates, with full pricing breakdowns for cash and reward stays. The response includes room metadata (occupancy caps, descriptions), per-rate-plan cash totals with taxes and fees, and a points/cash redemption ladder when IHG One Rewards inventory is available.
Endpoint URL
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| hotel_code | string (3–10 chars) | Required |
IHG hotel mnemonic. Examples: USMKM (Kimpton Maa-Lai Bangkok), LONHB (InterContinental London), ATLPS (InterContinental Atlanta).
|
| check_in | string (YYYY-MM-DD) | Required | Check-in date. Must not be in the past. |
| check_out | string (YYYY-MM-DD) | Required |
Check-out date. Must be strictly after check_in.
|
| adults | integer (1–8) | Optional |
Number of adult guests per room. Default: 2.
|
| children | integer (0–6) | Optional |
Number of children per room. Default: 0.
|
| rooms | integer (1–9) | Optional |
Number of rooms requested. Default: 1.
|
Finding the hotel code
IHG mnemonics appear in every ihg.com booking URL. For example, https://www.ihg.com/kimptonhotels/hotels/us/en/maikhao/usmkm/hoteldetail exposes usmkm as the hotel code (case-insensitive, normalized to uppercase server-side).
Brand coverage
The endpoint covers every IHG-branded property worldwide:
Response Format
Top-level fields
| Field | Type | Description |
|---|---|---|
| success | boolean | Always true on a 2xx response. |
| hotel_code | string | Echoes the IHG mnemonic from the request. |
| currency | string | Property's local billing currency. Applies to every entry in rates[]. |
| brand_code | string | IHG brand code (e.g. KIKI Kimpton, ICON InterContinental, HEXS Holiday Inn Express). |
| country_code | string | ISO 3166-1 alpha-2 country code. |
| total | integer | Number of room_types returned. |
| room_types | array of object | One entry per IHG inventory code. See below. |
room_types[] entry
| Field | Type | Description |
|---|---|---|
| code | string | IHG inventory code (e.g. CPUG, KOTN). Stable identifier for the room type at this property. |
| name | string | Display name from IHG's PMS (e.g. "Essential Room", "1 King Sea View"). |
| description | string | null | Long-form room description. |
| max_adults | integer | null | Adult occupancy cap for this room type. |
| max_children | integer | null | Child occupancy cap for this room type. |
| available_rooms | integer | null | Number of bookable rooms IHG reports for the requested dates. |
| rates | array of object | Cash rate plans available for this room. See below. |
| reward_options | array of object | IHG One Rewards redemption options for this room. May be [] when IHG doesn't price reward inventory for the room/dates. See below. |
rates[] entry — cash bookings
| Field | Type | Unit | Description |
|---|---|---|---|
| name | string | — | Display name (e.g. "Best Flexible Rate"). |
| rate_plan_code | string | — | IHG rate plan code (e.g. IGCOR, IDME0, IDAPF). |
| per_night | number | null | per night, pre-tax | Average nightly rate before taxes and fees. |
| per_night_after_tax | number | null | per night, post-tax | Average nightly rate including taxes and fees. |
| base_total | number | null | stay total, pre-tax | Stay total before taxes and fees. |
| fees_taxes | number | null | stay total | Combined taxes and fees for the stay. |
| total | number | null | stay total, post-tax | Final stay total. Equals base_total + fees_taxes. |
| currency | string | — | Always equals the top-level currency. |
| is_member_rate | boolean | — | true if booking requires an IHG One Rewards account. |
| is_advance_purchase | boolean | — | true for non-refundable prepay rates. |
| long_description | string | null | — | Human-readable rate description from IHG. |
| policy_description | string | null | — | Cancellation/prepayment policy text. |
reward_options[] entry — IHG One Rewards
| Field | Type | Unit | Description |
|---|---|---|---|
| points | integer | per night | IHG One Rewards points required per night. |
| cash | number | null | per night | Cash component per night. null for points-only options. |
| cash_currency | string | null | — | Currency code for the cash field. null when cash is null. Always read this field per entry — IHG may return a different currency than the property's rates[] currency. |
| points_total | integer | null | stay total | Total points required for the entire stay. |
| cash_total | number | null | stay total | Total cash for the entire stay. null for points-only options. |
Currency varies between rates and reward options
The top-level currency field applies to every entry in rates[]. For reward_options[], IHG returns its own currency on each entry — read cash_currency per option. In current observations IHG returns "USD" for the cash component of reward options regardless of the property's local currency, but always use the value from the response rather than hard-coding it.
Example response (200 OK)
Trimmed for brevity (one room, two cash rates). Real responses contain every available room type at the property, each with its own rates[] and reward_options[].
{
"success": true,
"hotel_code": "USMKM",
"currency": "THB",
"brand_code": "KIKI",
"country_code": "TH",
"total": 13,
"room_types": [
{
"code": "CPUG",
"name": "Essential Room",
"description": "You deserve a room as unique as you are. ...",
"max_adults": 2,
"max_children": 1,
"available_rooms": 9,
"rates": [
{
"name": "Best Flexible Rate",
"rate_plan_code": "IGCOR",
"per_night": 15562.43,
"per_night_after_tax": 18472.61,
"base_total": 31124.85,
"fees_taxes": 5820.36,
"total": 36945.21,
"currency": "THB",
"is_member_rate": false,
"is_advance_purchase": false,
"long_description": "Best Flexible Rate.",
"policy_description": "Restrictions may apply."
}
// ... more cash rate plans
],
"reward_options": [
{ "points": 79500, "cash": null, "cash_currency": null, "points_total": 159000, "cash_total": null },
{ "points": 59500, "cash": 149.0, "cash_currency": "USD", "points_total": 119000, "cash_total": 298.0 },
{ "points": 49500, "cash": 219.0, "cash_currency": "USD", "points_total": 99000, "cash_total": 438.0 },
{ "points": 39500, "cash": 279.0, "cash_currency": "USD", "points_total": 79000, "cash_total": 558.0 },
{ "points": 29500, "cash": 334.0, "cash_currency": "USD", "points_total": 59000, "cash_total": 668.0 },
{ "points": 19500, "cash": 384.0, "cash_currency": "USD", "points_total": 39000, "cash_total": 768.0 },
{ "points": 9500, "cash": 419.0, "cash_currency": "USD", "points_total": 19000, "cash_total": 838.0 }
]
}
// ... more room types
]
}
Working with the response
Find the cheapest cash rate for a room
Sort or reduce rates by total (whole-stay including taxes and fees):
cheapest = min(room["rates"], key=lambda r: r["total"])
print(f"{cheapest['rate_plan_code']}: {cheapest['total']} {cheapest['currency']}")
Find the points-only redemption option
Filter reward_options for the entry where cash is null. There is at most one points-only entry, and it may not exist for every room/date combination:
points_only = next(
(o for o in room["reward_options"] if o["cash"] is None),
None,
)
if points_only:
print(f"{points_only['points']} points/night")
else:
print("no points-only option")
Empty reward_options is expected
When IHG can't price reward inventory for a room+dates combination, that room's reward_options array is []. This is a normal response, not an error — other rooms in the same response may still have full ladders.
Common Use Cases
Real-time availability
Display current room availability, prices, and inventory counts for IHG properties without scraping ihg.com.
Multi-room comparison
Show every room type at a property side-by-side with full price breakdowns and policy details.
Loyalty-aware booking flows
Surface IHG One Rewards points and points+cash redemption options alongside cash rates in your booking flow.
Hotel data enrichment
Enrich your hotel records with IHG-side room metadata, occupancy caps, and rate-plan details.
Error Responses
All endpoint-level errors follow RFC 7807 Problem Details with content type application/problem+json. Each response carries provider: "ihg", product: "rooms", and a unique correlation_id for support requests.
400 Bad Request — invalid date format
check_in or check_out isn't YYYY-MM-DD.
{
"type": "https://api.stayapi.com/errors/invalid-date-format",
"title": "Invalid Date Format",
"status": 400,
"detail": "Date must be in YYYY-MM-DD format",
"instance": "/v1/ihg/rooms",
"provider": "ihg",
"product": "rooms",
"error_code": "INVALID_DATE_FORMAT",
"correlation_id": "ad0607ed-c7b0-4a7a-b17e-ac49dec27a94"
}
400 Bad Request — past dates
check_in is before today.
{
"type": "https://api.stayapi.com/errors/past-dates",
"title": "Past Dates",
"status": 400,
"detail": "Check-in date cannot be in the past",
"instance": "/v1/ihg/rooms",
"provider": "ihg",
"product": "rooms",
"error_code": "PAST_DATES",
"correlation_id": "745b8a26-d79e-4a99-8b31-dc2122022f8c"
}
400 Bad Request — invalid date order
check_out isn't strictly after check_in.
{
"type": "https://api.stayapi.com/errors/invalid-dates",
"title": "Invalid Dates",
"status": 400,
"detail": "Check-out date must be after check-in date",
"instance": "/v1/ihg/rooms",
"provider": "ihg",
"product": "rooms",
"error_code": "INVALID_DATES",
"correlation_id": "bb4fec53-19b8-4056-a456-d4ec8202018b"
}
404 Not Found — unknown hotel code
IHG doesn't recognize the supplied hotel_code.
{
"type": "https://api.stayapi.com/errors/hotel-not-found",
"title": "Hotel Not Found",
"status": 404,
"detail": "Hotel code not recognized by IHG: ZZZZZ",
"instance": "/v1/ihg/rooms",
"provider": "ihg",
"product": "rooms",
"error_code": "HOTEL_NOT_FOUND",
"correlation_id": "29caac72-47db-4316-ab26-3aeb8c8c1264"
}
502 Bad Gateway — upstream error
IHG's availability service returned a non-2xx response (5xx, 429, etc.) after our retry budget was exhausted. The upstream_status field carries the upstream HTTP code.
{
"type": "https://api.stayapi.com/errors/upstream-error",
"title": "Upstream Error",
"status": 502,
"detail": "Failed to fetch room data: HTTP 503",
"instance": "/v1/ihg/rooms",
"provider": "ihg",
"product": "rooms",
"error_code": "UPSTREAM_ERROR",
"correlation_id": "6bc0f955-18c9-4567-9183-75d5c01117b6",
"upstream_status": 503
}
Authentication errors
A missing or invalid x-api-key header returns a global authentication error (HTTP 401 or 422). The body shape differs from the endpoint-level errors above and is documented on the Authentication page.