Everything we hold on one hotel.
The full profile: gallery, rooms and their listings, venues, policies, reviews and prices for a stay.
images.count · 182
rooms[].listings[]
sections=core,images,rooms
One call returns the whole profile. Ask for fewer sections to keep it small. Prices appear only when you send check_in and check_out; there are no undated prices.
Pass the search_id from a search made in the last 30 minutes and the detail is already warm. The price is the same either way.
/v2/hotels/{hotel_id}/v2/amenities/v2/engines/v2/health/v2/openapi.jsonHotel detail
/v2/hotels/{hotel_id}Synchronous; needs the content scope and bills hotel.detail once per call. Prices appear only when check_in and check_out are both set; rates=refresh also starts a rates.live job, which needs the rates scope and the Build plan or higher and bills rates.direct.live when it completes. sections limits the response to the parts you ask for.
hotel.detail per call. rates=refresh also starts a live rates job, billed as rates.direct.live when it completes.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
hotel_idREQUIRED | path | string (uuid) | The hotel's hotel_id (uuid), as returned by resolve or search. |
sections | query | object | Comma-separated sections to return, any of core, images, rooms, venues, policies, facts, reviews, guest_voice, rates, location; all of them when omitted. |
check_in | query | string (date) | Arrival date, YYYY-MM-DD; rates are only returned when both dates are set. |
check_out | query | string (date) | Departure date, YYYY-MM-DD, after check_in and sent together with it. |
adults | query | object | Adults across all rooms for the rates lookup; defaults to 2 per room. |
children_ages | query | object | Comma-separated ages (0-17) of the children; cached rates cover adults-only parties, so any child returns no prices and a rates_party_unsupported warning. |
rooms | query | object | Number of rooms for the rates lookup; defaults to 1. |
currency | query | object | ISO 4217 currency of the caller; prices are never converted and stay in the currency they were observed in. |
locale | query | object | Language for descriptions and other translated text, as a language tag (pt-BR reads as pt); English when omitted or untranslated. |
search_id | query | object | The search_id of a recent search that returned this hotel, which lets the call reuse the content that search prepared; the price is the same. |
rates | query | string | cached serves stored observations; refresh also starts a live rates job (needs the rates scope and the Build plan, billed rates.direct.live). One of cached, refresh. |
image_width | query | integer | Width in pixels of every image URL returned: 640, 1024 or 1600. One of 640, 1024, 1600. |
reviews_limit | query | integer | Maximum review items in reviews.items. |
Example
curl 'https://api.vistalink.com/v2/hotels/43d0be71-5f3c-4c8e-9a52-1d7e2b6f0a19?sections=core%2Cimages%2Crooms%2Crates&check_in=2026-11-14&check_out=2026-11-16&adults=2¤cy=EUR&search_id=srch_3f9c2a7e4b1d4c8a9e6f0b2d5a7c1e93' \
-H "Authorization: Bearer $VISTALINK_API_KEY"{
"billing": {
"amount": "0.005",
"currency": "USD",
"sku": "hotel.detail",
"units": 1
},
"core": {
"amenities": [
"POOL"
],
"check_in_time": "15:00",
"check_out_time": "11:00",
"description": "Boutique hotel near the Trevi Fountain.",
"hotel_type": "hotel",
"languages": [
"en",
"it"
],
"name": "Umiltà 36",
"operating_status": "open",
"phone": "+39 06 000000",
"review_count": 2056,
"review_score": 9.1,
"short_character": "quiet, central",
"star_rating": 5,
"website_url": "https://umilta36.com"
},
"hotel_id": "43d0be71-5f3c-4c8e-9a52-1d7e2b6f0a19",
"images": {
"count": 182,
"hero": {
"image_id": "a1f3c5e7-9b2d-4f6a-8c0e-2d4f6a8c0e1b",
"label": "building",
"url": "https://images.vistalink.com/h/43d0be71/ext.jpg?w=1024"
},
"items": [
{
"height": 683,
"image_id": "b2e4d6f8-0a1c-4e3a-9d5b-7f9a1c3e5d2c",
"label": "room",
"position": 1,
"url": "https://images.vistalink.com/h/43d0be71/room.jpg?w=1024",
"width": 1024
}
]
},
"location": {
"address": "Via dell'Umiltà 36",
"city": "Rome",
"country": "IT",
"lat": 41.9,
"lng": 12.48,
"neighbourhood_text": "Trevi",
"transport_notes": "Metro A Barberini, 600 m"
},
"provenance": {
"images_release": "7c1e9a3f-2b4d-4e6a-8f0c-5d9b1a3e7f24",
"profile_source": "site",
"profile_updated_at": "2026-10-07T09:30:00Z"
},
"rates": {
"channels": [
{
"channel": "direct",
"engine": "SYNXIS",
"observed_at": "2026-10-07T09:30:00Z",
"offers": [
{
"availability": "available",
"board": "breakfast",
"channel": "direct",
"currency": "EUR",
"engine": "SYNXIS",
"excluded_charges": [],
"free_cancellation": false,
"includes_taxes": true,
"listing_key": "engine_room:1234567",
"nightly_avg": "481.00",
"observed_at": "2026-10-07T09:30:00Z",
"occupancy": {
"adults": 2,
"children_ages": []
},
"offer_id": "off_t3c8e1a9b4f2d7e6a5c0b",
"rate_name": "Non-refundable, breakfast included",
"room_id": "5b1e2f3a-0c4d-4e5f-8a9b-1c2d3e4f5a6b",
"room_name": "Superior Room",
"total": "962.00",
"url": "https://umilta36.com/book?checkin=2026-11-14&checkout=2026-11-16"
}
],
"status": "observed"
}
],
"stay": {
"check_in": "2026-11-14",
"check_out": "2026-11-16",
"rooms": [
{
"adults": 2,
"children_ages": []
}
]
}
},
"request_id": "req_8f2c1a9b3d4e5f60",
"rooms": [
{
"accessible": false,
"amenities": [
"AIR_CONDITIONING"
],
"balcony": false,
"bed_config": [
{
"count": 1,
"type": "king"
}
],
"description": "City view.",
"images": [],
"kitchen": false,
"listings": [
{
"listing_key": "site:superior",
"match_confidence": "high",
"name": "Superior Double Room",
"provider": "umilta36.com",
"source": "site",
"url": "https://umilta36.com/rooms/superior"
}
],
"max_occupancy": 3,
"name": "Superior Room",
"occupancy": 2,
"offers": [
{
"availability": "available",
"board": "breakfast",
"channel": "direct",
"currency": "EUR",
"engine": "SYNXIS",
"excluded_charges": [],
"free_cancellation": false,
"includes_taxes": true,
"listing_key": "engine_room:1234567",
"nightly_avg": "481.00",
"observed_at": "2026-10-07T09:30:00Z",
"occupancy": {
"adults": 2,
"children_ages": []
},
"offer_id": "off_t3c8e1a9b4f2d7e6a5c0b",
"rate_name": "Non-refundable, breakfast included",
"room_id": "5b1e2f3a-0c4d-4e5f-8a9b-1c2d3e4f5a6b",
"room_name": "Superior Room",
"total": "962.00",
"url": "https://umilta36.com/book?checkin=2026-11-14&checkout=2026-11-16"
}
],
"room_id": "5b1e2f3a-0c4d-4e5f-8a9b-1c2d3e4f5a6b",
"size_m2": 28,
"views": [
"city"
]
}
],
"sections_present": [
"core",
"location",
"images",
"rooms",
"rates"
]
}Response 200
Successful Response
| Field | Type | Description |
|---|---|---|
request_idREQUIRED | string | Opaque id of this request, also sent as the X-Request-Id header; quote it when contacting support. |
billing | Billing | null | What a billed call cost. Present on every billed response; billing is null on free ones. |
hotel_idREQUIRED | string (uuid) | The hotel's id. |
sections_present | string[] | Requested sections that have data for this hotel, in a fixed order; rates is listed only when some channel has prices. |
core | object | null | Identity, ratings and contact details. |
core.nameREQUIRED | string | Hotel name. |
core.hotel_type | string | null | Kind of property as catalogued, free text such as hotel; null when unknown. |
core.star_rating | number | null | Official star rating, 1 to 5; null when unrated. |
core.review_score | number | null | Average guest review score on a 0 to 10 scale; null when there are no reviews. |
core.review_count | integer | null | Number of guest reviews behind review_score, which can differ from reviews.count (the reviews we hold). |
core.description | string | null | Long description of the hotel in locale when translated, else English; null when there is none. |
core.short_character | string | null | One line on what the hotel is like, from its published profile; null without a profile. |
core.chain | string | null | Hotel chain the property belongs to; null when independent or unknown. |
core.brand | string | null | Brand within the chain; null when none or unknown. |
core.operating_status | string | null | Whether the hotel is trading, for example open, closed_temporarily, closed, opening_soon or unknown; null without a profile. |
core.check_in_time | string | null | Earliest check-in time, usually HH:MM in local time; null when unknown. |
core.check_out_time | string | null | Latest check-out time, usually HH:MM in local time; null when unknown. |
core.phone | string | null | Hotel phone number as published. |
core.website_url | string (uri) | null | The hotel's own website. |
core.booking_url | string (uri) | null | The hotel's listing URL on the third-party channel; null when it has none. |
core.amenities | string[] | Uppercase amenity codes, as listed by GET /v2/amenities. |
core.languages | string[] | Languages the staff speak, as listed in the hotel profile, for example en; empty when unknown. |
location | object | null | Position, address and getting there. |
location.lat | number | null | Latitude in decimal degrees. |
location.lng | number | null | Longitude in decimal degrees. |
location.address | string | null | Street address on one line: street and number, postcode, city. |
location.city | string | null | City the hotel is in. |
location.country | string | null | ISO 3166-1 alpha-2 country code, or the country name when no code is known. |
location.neighbourhood_text | string | null | A paragraph on the neighbourhood, in locale when translated; null without a profile. |
location.transport_notes | string | null | How to get there by public transport, in locale when translated; null without a profile. |
images | object | null | Gallery in curated order. |
images.hero | object | null | The lead image; null when the hotel has no images. |
images.hero.image_id | string (uuid) | null | Image id; the same image keeps the same id across responses. |
images.hero.urlREQUIRED | string (uri) | CDN URL of the image at image_width pixels wide (never upscaled). |
images.hero.label | string | null | What the image shows, for example building, room, bathroom or swimming pool outdoor; null when unlabelled. |
images.hero.room_id | string (uuid) | null | The room this image shows, matching rooms[].room_id; null for images of the hotel as a whole. |
images.hero.width | integer | null | Width in pixels of the image at url; null when unknown. |
images.hero.height | integer | null | Height in pixels of the image at url; null when unknown. |
images.hero.position | integer | null | 1-based position in gallery order; null on hero and venue images. |
images.count | integer | How many distinct images the hotel has, which can exceed the 50 in items. Default 0. |
images.items | DetailImage[] | Up to 50 images in gallery order. |
images.items[].image_id | string (uuid) | null | Image id; the same image keeps the same id across responses. |
images.items[].urlREQUIRED | string (uri) | CDN URL of the image at image_width pixels wide (never upscaled). |
images.items[].label | string | null | What the image shows, for example building, room, bathroom or swimming pool outdoor; null when unlabelled. |
images.items[].room_id | string (uuid) | null | The room this image shows, matching rooms[].room_id; null for images of the hotel as a whole. |
images.items[].width | integer | null | Width in pixels of the image at url; null when unknown. |
images.items[].height | integer | null | Height in pixels of the image at url; null when unknown. |
images.items[].position | integer | null | 1-based position in gallery order; null on hero and venue images. |
rooms | DetailRoom[] | null | Physical room types with their listings and prices. |
rooms[].room_id | string (uuid) | null | Room id, stable across responses and used by Offer.room_id. |
rooms[].nameREQUIRED | string | Room name. |
rooms[].description | string | null | Room description in locale when translated, else English; null when there is none. |
rooms[].size_m2 | number | null | Room size in square metres; null when unknown. |
rooms[].occupancy | integer | null | Standard number of guests the room is sold for; null when unknown. |
rooms[].max_occupancy | integer | null | Most guests the room can hold, including extra beds; equals occupancy when no maximum is known. |
rooms[].bed_config | BedConfig[] | Beds in the room; empty when unknown. |
rooms[].bed_config[].typeREQUIRED | string | Bed type as the source names it, for example king, double, twin or sofa bed. |
rooms[].bed_config[].count | integer | Number of beds of this type. Default 1. |
rooms[].views | string[] | Views from the room, for example city or sea. |
rooms[].balcony | boolean | null | True when the room has a balcony or terrace, false when it does not, null when unknown. |
rooms[].accessible | boolean | null | True when the room is wheelchair accessible, false when it is not, null when unknown. |
rooms[].kitchen | boolean | null | True when the room has a kitchen or kitchenette, false when it does not, null when unknown. |
rooms[].amenities | string[] | Uppercase amenity codes of the room. |
rooms[].images | DetailImage[] | Up to 6 images of the room. |
rooms[].images[].image_id | string (uuid) | null | Image id; the same image keeps the same id across responses. |
rooms[].images[].urlREQUIRED | string (uri) | CDN URL of the image at image_width pixels wide (never upscaled). |
rooms[].images[].label | string | null | What the image shows, for example building, room, bathroom or swimming pool outdoor; null when unlabelled. |
rooms[].images[].room_id | string (uuid) | null | The room this image shows, matching rooms[].room_id; null for images of the hotel as a whole. |
rooms[].images[].width | integer | null | Width in pixels of the image at url; null when unknown. |
rooms[].images[].height | integer | null | Height in pixels of the image at url; null when unknown. |
rooms[].images[].position | integer | null | 1-based position in gallery order; null on hero and venue images. |
rooms[].listings | RoomListing[] | The same room on other channels, matched to this room. |
rooms[].listings[].sourceREQUIRED | string | Where the listing is: site (the hotel's website), engine (its booking engine), booking (the third-party channel) or expedia. One of booking, site, engine, expedia. |
rooms[].listings[].provider | string | null | Who publishes the listing, for example official_site or the booking engine's name. |
rooms[].listings[].name | string | null | Room name as that listing shows it. |
rooms[].listings[].listing_key | string | null | The listing's own key, such as room_type:1234567, matching Offer.listing_key where the channel has one. |
rooms[].listings[].url | string (uri) | null | Page of the listing; null when there is none. |
rooms[].listings[].match_confidence | string | null | How sure the match between this listing and the room is: high or medium (low-confidence candidates are not shown); null when not scored. One of high, medium, low. |
rooms[].offers | Offer[] | Prices for this room for the requested stay; empty without dates or when none were observed. |
venues | Venue[] | null | Restaurants, bars, spa and other places at the hotel. |
venues[].venue_id | string | null | Venue id, stable across responses. |
venues[].kindREQUIRED | string | What the venue is, for example dining, bar, cafe, spa, pool, gym, beach or kids. |
venues[].section | string | null | Group the venue is shown under: dining, wellness, activities, families, business, parking, transport, shops or spaces. |
venues[].name | string | null | Venue name, in locale when translated. |
venues[].summary | string | null | A short description, in locale when translated. |
venues[].cuisine | string | null | Type of cuisine for dining venues, free text such as seafood; null otherwise. |
venues[].opening_hours | string | null | Opening hours as one line of free text; null when not published. |
venues[].price_point | string | null | Price level, free text such as $$$; null when unknown. |
venues[].access | VenueAccess[] | Who may use the venue and on what terms. |
venues[].access[].subjectREQUIRED | string | Who the rule is for: hotel (all guests), or room:<room_id>, board_basis:<key> or audience:<key> for a subset. |
venues[].access[].accessREQUIRED | string | Terms of use, for example included, surcharge, members, restricted or adults_only. |
venues[].items | VenueItem[] | Menu items or services offered. |
venues[].items[].nameREQUIRED | string | Item name, in locale when translated. |
venues[].items[].price_text | string | null | Price as published, free text such as EUR 18; null when not published. |
venues[].images | DetailImage[] | Images of the venue. |
venues[].images[].image_id | string (uuid) | null | Image id; the same image keeps the same id across responses. |
venues[].images[].urlREQUIRED | string (uri) | CDN URL of the image at image_width pixels wide (never upscaled). |
venues[].images[].label | string | null | What the image shows, for example building, room, bathroom or swimming pool outdoor; null when unlabelled. |
venues[].images[].room_id | string (uuid) | null | The room this image shows, matching rooms[].room_id; null for images of the hotel as a whole. |
venues[].images[].width | integer | null | Width in pixels of the image at url; null when unknown. |
venues[].images[].height | integer | null | Height in pixels of the image at url; null when unknown. |
venues[].images[].position | integer | null | 1-based position in gallery order; null on hero and venue images. |
policies | Policy[] | null | House rules and terms. |
policies[].kindREQUIRED | string | Policy topic, for example checkin, checkout, children, extra_bed, pets, smoking, cancellation, deposit, payment, city_tax, breakfast, parking or other. |
policies[].summary | string | null | The policy in one or two sentences, in locale when translated. |
policies[].structured | object | null | The policy's terms as key-value data when the source gives them, for example times or age limits; shape depends on kind. |
facts | Fact[] | null | Other facts about the hotel. |
facts[].kindREQUIRED | string | Fact topic, for example history_moment, brand, loyalty, language, trivia, transport_distance, sustainability_practice or other. |
facts[].labelREQUIRED | string | Short heading for the fact. |
facts[].valueREQUIRED | string | The fact itself as text, in locale when translated. |
notices | Notice[] | null | Temporary notices; returned with core. |
notices[].severity | string | info, warning or critical. One of info, warning, critical. Default info. |
notices[].titleREQUIRED | string | Notice heading, in locale when translated. |
notices[].body | string | null | Notice text, in locale when translated. |
notices[].valid_to | string (date-time) | null | Last day the notice applies, at midnight with no time zone; null when open-ended. |
reviews | object | null | Guest reviews. |
reviews.count | integer | Number of reviews we hold, which can differ from core.review_count. Default 0. |
reviews.category_scores | map of number | Average score per category on a 0 to 10 scale, keyed by the category's display name, for example Cleanliness, Staff or Location. |
reviews.items | ReviewItem[] | Up to reviews_limit reviews, newest first. |
reviews.items[].review_id | string | null | Review id. |
reviews.items[].rating | number | null | The guest's score on a 0 to 10 scale. |
reviews.items[].title | string | null | Review headline. |
reviews.items[].positive | string | null | What the guest liked. |
reviews.items[].negative | string | null | What the guest disliked. |
reviews.items[].traveller_type | string | null | Kind of trip as the source records it, for example Couple, Family, Solo traveller, Business or Group. |
reviews.items[].date | string | null | Date we collected the review, YYYY-MM-DD; not the date of the stay. |
guest_voice | object | null | Themes from guest reviews. |
guest_voice.praised | VoiceTheme[] | Up to 6 themes with sentiment 0.5 or higher, most positive first. |
guest_voice.praised[].typeREQUIRED | string | Theme, for example location, service, cleanliness, rooms, food, value, noise or views. |
guest_voice.praised[].summary | string | null | What guests say about the theme, in one or two sentences. |
guest_voice.praised[].sentiment | number | null | How positive guests are on the theme, from 0 (negative) to 1 (positive). |
guest_voice.praised[].quotes | string[] | Up to 3 verbatim quotes from this hotel's reviews. |
guest_voice.watch_outs | VoiceTheme[] | Up to 4 themes with sentiment 0.4 or lower, most negative first. |
guest_voice.watch_outs[].typeREQUIRED | string | Theme, for example location, service, cleanliness, rooms, food, value, noise or views. |
guest_voice.watch_outs[].summary | string | null | What guests say about the theme, in one or two sentences. |
guest_voice.watch_outs[].sentiment | number | null | How positive guests are on the theme, from 0 (negative) to 1 (positive). |
guest_voice.watch_outs[].quotes | string[] | Up to 3 verbatim quotes from this hotel's reviews. |
rates | object | null | Stored prices for the stay. |
rates.stay | object | null | The stay the prices are for; null when no dates were given. |
rates.stay.check_in | string (date) | null | Arrival date, YYYY-MM-DD. |
rates.stay.check_out | string (date) | null | Departure date, YYYY-MM-DD. |
rates.stay.rooms | Occupancy[] | The party per room; a party read from the query is split evenly over its rooms and has no children. |
rates.stay.rooms[].adultsREQUIRED | integer | Adults in the room. |
rates.stay.rooms[].children_ages | integer[] | Age of each child in the room; empty for adults only. |
rates.stay.origin | string | null | query when the stay was read from the query text, filters when it came from filters.stay; null on hotel detail. One of query, filters. |
rates.channels | RateChannel[] | Prices per channel, direct first; empty without dates, for parties with children, or when nothing was observed. |
rates.channels[].channelREQUIRED | string | direct for the hotel's own booking engine, third_party for the Enterprise third-party channel. One of direct, third_party, expedia. |
rates.channels[].engine | string | null | Code of the hotel's booking engine on the direct channel, for example SYNXIS; null on the third-party channel. |
rates.channels[].statusREQUIRED | string | observed when seen recently (within 4 hours for stays in the next 14 days, else 24 hours) or stale when older but within 7 days; channels with no prices are left out. One of observed, stale, unknown, unsupported. |
rates.channels[].observed_at | string (date-time) | null | When the newest price on this channel was observed, RFC 3339 UTC. |
rates.channels[].offers | Offer[] | Prices for each room and rate, cheapest first, sold-out last. |
rates.refresh_job | object | null | The live rates job started by rates=refresh; its result arrives through GET /v2/jobs/{job_id} or the rates.completed webhook. Null otherwise. |
rates.refresh_job.job_idREQUIRED | string | Job id; poll it with GET /v2/jobs/{job_id}. |
provenance | object | null | Where the content comes from. |
provenance.profile_source | string | null | Main source of the published profile: site (the hotel's website) or booking (the third-party channel); null without a profile. One of site, booking. |
provenance.profile_updated_at | string (date-time) | null | When the profile was last updated, RFC 3339 UTC. |
provenance.images_release | string | null | Id of the gallery release the image order comes from; null when the images section was not requested or the hotel is not in a release. |
warnings | DetailWarning[] | Things the call could not fully do. |
warnings[].codeREQUIRED | string | rates_party_unsupported (stored rates cover adults-only parties), channel_unavailable (the third-party channel was left out), refresh_requires_dates or refresh_unavailable (no live job was started). One of rates_party_unsupported, channel_unavailable, refresh_requires_dates, refresh_unavailable. |
warnings[].message | string | null | Explanation in English. |
warnings[].channel | string | null | The channel left out, third_party; set only on channel_unavailable. Always third_party. |
Errors
| Status | Code | When |
|---|---|---|
| 400 | bad_request | Validation errors carry details.fields[]. |
| 401 | unauthorized | No key, or the key is unknown or revoked. |
| 402 | insufficient_credit | Not enough credit for the call. Checked before any work starts, so nothing was billed. |
| 403 | forbidden | Missing scope, or details.reason tier_required: this needs the Build plan or higher. |
| 404 | not_found | The hotel, offer, booking, job or webhook doesn't exist for this key. |
| 429 | rate_limited | Over the per-minute limit for the tier. Wait Retry-After seconds. |
| 503 | unavailable | We're temporarily unable to serve the call. Retry with backoff. |
Amenity codes
/v2/amenitiesSynchronous and free; any valid key. The codes filters.amenities accepts; a kind: group code matches any of its members.
Example
curl 'https://api.vistalink.com/v2/amenities' \
-H "Authorization: Bearer $VISTALINK_API_KEY"{
"amenities": [
{
"category": "pool",
"code": "POOL",
"kind": "group",
"label": "Pool (any)",
"members": [
"POOL_OUTDOOR",
"POOL_INDOOR",
"POOL_HEATED",
"POOL_ROOFTOP",
"POOL_WITH_VIEW"
]
},
{
"category": "pool",
"code": "POOL_ROOFTOP",
"kind": "amenity",
"label": "Rooftop pool",
"members": []
}
],
"request_id": "req_8f2c1a9b3d4e5f60"
}Response 200
Successful Response
| Field | Type | Description |
|---|---|---|
request_idREQUIRED | string | Opaque id of this request, also sent as the X-Request-Id header; quote it when contacting support. |
billing | Billing | null | What a billed call cost. Present on every billed response; billing is null on free ones. |
amenitiesREQUIRED | Amenity[] | Every amenity and group code. |
amenities[].codeREQUIRED | string | Uppercase code, for example POOL_ROOFTOP. |
amenities[].labelREQUIRED | string | Readable name in English. |
amenities[].categoryREQUIRED | string | Group the code belongs to, for example pool, wellness, parking or connectivity. |
amenities[].kind | string | amenity for a single amenity, group for a code that matches any of its members. One of amenity, group. Default amenity. |
amenities[].members | string[] | For a group, the codes it matches; empty for a single amenity. |
Errors
| Status | Code | When |
|---|---|---|
| 400 | bad_request | Validation errors carry details.fields[]. |
| 401 | unauthorized | No key, or the key is unknown or revoked. |
| 403 | forbidden | Missing scope. |
| 429 | rate_limited | Over the per-minute limit for the tier. Wait Retry-After seconds. |
| 503 | unavailable | We're temporarily unable to serve the call. Retry with backoff. |
Supported booking engines
/v2/enginesSynchronous and free; any valid key. Booking engines we read prices from or book on, with their capabilities and hotel counts.
Example
curl 'https://api.vistalink.com/v2/engines' \
-H "Authorization: Bearer $VISTALINK_API_KEY"{
"engines": [
{
"book": true,
"engine": "SYNXIS",
"hotel_count": 1830,
"live_rates": true,
"name": "SynXis",
"success_class": "unmeasured"
}
],
"request_id": "req_8f2c1a9b3d4e5f60"
}Response 200
Successful Response
| Field | Type | Description |
|---|---|---|
request_idREQUIRED | string | Opaque id of this request, also sent as the X-Request-Id header; quote it when contacting support. |
billing | Billing | null | What a billed call cost. Present on every billed response; billing is null on free ones. |
enginesREQUIRED | Engine[] | Supported engines, most hotels first. |
engines[].engineREQUIRED | string | Engine code, as Offer.engine and RateChannel.engine report it, for example SYNXIS. |
engines[].nameREQUIRED | string | Engine name. |
engines[].live_ratesREQUIRED | boolean | True when direct prices can be read live for hotels on this engine. |
engines[].bookREQUIRED | boolean | True when bookings can be made on this engine. |
engines[].success_class | string | Measured booking success rate band: high, medium, low, or unmeasured (the value for every engine today). One of high, medium, low, unmeasured. Default unmeasured. |
engines[].hotel_count | integer | null | Indexed hotels on this engine; null when none or not counted. |
Errors
| Status | Code | When |
|---|---|---|
| 400 | bad_request | Validation errors carry details.fields[]. |
| 401 | unauthorized | No key, or the key is unknown or revoked. |
| 403 | forbidden | Missing scope. |
| 429 | rate_limited | Over the per-minute limit for the tier. Wait Retry-After seconds. |
| 503 | unavailable | We're temporarily unable to serve the call. Retry with backoff. |
Health
/v2/healthPublic: no key, free, synchronous. 200 when every dependency is up, 503 with the same body when one is down.
Example
curl 'https://api.vistalink.com/v2/health'{
"checks": {
"database": "ok"
},
"request_id": "req_8f2c1a9b3d4e5f60",
"status": "ok",
"version": "2.0"
}Response 200
Successful Response
| Field | Type | Description |
|---|---|---|
statusREQUIRED | string | ok when every dependency is up (HTTP 200), degraded when one is down (HTTP 503). One of ok, degraded. |
version | string | API version, 2.0. Default 2.0. |
checks | map of string | State of each dependency checked, keyed by name (database): ok or unavailable. |
request_id | string | null | Id of this request. |
Errors
| Status | Code | When |
|---|---|---|
| 503 | | Degraded. |
This OpenAPI document
/v2/openapi.jsonPublic: no key, free, synchronous. The OpenAPI 3.1 document for /v2, the same file the docs, SDKs and CLI are generated from.
Example
curl 'https://api.vistalink.com/v2/openapi.json'{}Response 200
OpenAPI 3.1 document
Catalog helpers
GET /v2/amenities lists the codes filters.amenities takes. An entry with kind: group (POOL) stands for every code in its members (indoor, outdoor, rooftop…); kind: amenity is a single feature.
GET /v2/engines lists the booking engines we read, keyed by engine, with live_rates, book and hotel_count. success_class is high, medium or low once we've measured an engine, and unmeasured until then.
GET /v2/health needs no key. It answers {status, checks, request_id}: status is ok, or degraded with a 503 and the failing dependency named in checks.
Shared objects.
Objects that appear in more than one place. Billing is on the Billing page and ErrorBody under Errors & limits.
Offer
One bookable price for one room and rate, as observed on a channel.
| Field | Type | Description |
|---|---|---|
offer_idREQUIRED | string | Offer id, off_t plus 20 hex characters, specific to your account; book it with POST /v2/bookings within 30 minutes of receiving it. |
channelREQUIRED | string | Where the price was observed: direct for the hotel's own booking engine, third_party for the Enterprise third-party channel. One of direct, third_party, expedia. |
engine | string | null | Code of the hotel's booking engine for direct offers, for example SYNXIS; null on the third-party channel. |
room_id | string (uuid) | null | Catalogue room this offer is for, matching rooms[].room_id on hotel detail; null when the source names the room only by its own code or name. |
room_name | string | null | Room name as the source shows it; null when the source does not name the room. |
listing_key | string | null | The source's own key for the room, such as engine_room:SUP or room_type:1234567; null when the source has none. |
rate_name | string | null | Rate plan name as the source shows it, or one built from the cancellation terms and board, such as Free cancellation, breakfast included. |
totalREQUIRED | string | Price for the whole stay and the whole party, a decimal string in currency; taxes the source quoted separately are added in when their amount is known. "0" when sold out. |
currencyREQUIRED | string | ISO 4217 currency the price was observed in; never converted. |
nightly_avg | string | null | total divided by the number of nights, for the whole party rather than per room; null when sold out. |
includes_taxes | boolean | null | True when total includes taxes and fees, false when some are listed in excluded_charges, null when the source does not say. |
excluded_charges | ExcludedCharge[] | Charges payable on top of total; usually empty. |
excluded_charges[].kindREQUIRED | string | What the charge is; taxes_and_fees (taxes and fees the source quoted separately) is the only kind produced today. |
excluded_charges[].amountREQUIRED | string | Amount of the charge, a decimal string in currency. |
excluded_charges[].currencyREQUIRED | string | ISO 4217 currency of amount. |
excluded_charges[].per | string | null | What amount is charged per: stay (once for the whole stay, the only basis produced today), night, person or person_night. One of night, stay, person, person_night. |
excluded_charges[].note | string | null | Short note on how the charge is applied, for example quoted on top of the total. |
board | string | null | Meals included: none, breakfast, half (breakfast and dinner), full (all meals) or all_inclusive; null when the source does not say. One of none, breakfast, half, full, all_inclusive. |
free_cancellation | boolean | null | True when the rate can be canceled free of charge, false when it is non-refundable, null when unknown. |
cancellation_deadline | string (date-time) | null | Last moment to cancel free of charge, RFC 3339; set only on offers read live, null otherwise. |
payment | string | null | When the guest pays: prepay at booking or pay_at_hotel at the property; null when the source does not say. One of prepay, pay_at_hotel. |
occupancy | object | null | The party this price is for, totalled across all rooms. |
occupancy.adultsREQUIRED | integer | Adults in the room. |
occupancy.children_ages | integer[] | Age of each child in the room; empty for adults only. |
availability | string | available when the room can be booked at this price, sold_out when the source showed it as unavailable, unknown when it did not say. One of available, sold_out, unknown. Default unknown. |
observed_at | string (date-time) | null | When this price was observed, RFC 3339 UTC. |
url | string (uri) | null | Page on the source where this price was observed; null when the source has no linkable page. |