Skip to content
ScoutingAPI
Docs

The unified schema

Every platform normalizes to the same shapes: Property, Availability, Price, PriceCompare and Review. One data model to code against, four platforms behind it.

Property

Returned by search and listing. The composite id is stable and case-sensitive.

Property
{
  "id": "stays_vrbo_5663861ha",            // composite: stays_<platform>_<platformListingId>, case-sensitive
  "platform": "vrbo",
  "platformListingId": "5663861ha",        // verbatim from the source platform
  "url": "https://www.vrbo.com/…",
  "name": "Awesome home in Pirovac with swimming pool",
  "propertyType": "house",                 // hotel | apartment | house | villa | cottage | other
  "location": { "lat": 43.82, "lng": 15.58, "city": "Murter", "region": "Sibenik-Knin", "country": "HR" },
  "starRating": null,                      // hotel class; null for short-term rentals
  "guestRating": 9.1, "ratingScale": 10, "reviewCount": 142,
  "maxOccupancy": 8, "bedrooms": 3, "bathrooms": 2,
  "amenities": ["pool", "kitchen", "air_conditioning"],
  "images": ["https://…"],                 // source URLs — ScoutingAPI never rehosts photos
  "host": { "name": "…", "isSuperhost": false },
  "price": { /* embedded Price when dates supplied; else absent */ }
}

Composite id is verbatim & case-sensitive

Availability

One entry per requested listing; each day reports availability, min-nights and whether check-in / check-out / booking is allowed.

Availability
{
  "platform": "airbnb",
  "listingId": "42307961",
  "dates": [
    { "date": "2026-07-13", "available": true, "minNights": 7, "checkIn": true, "checkOut": false, "bookable": true }
  ]
}

Price

A real numeric quote for specific dates and occupancy. Fees are null when the source doesn’t itemize them.

Price
{
  "platform": "booking",
  "listingId": "abramovic2",
  "currency": "EUR",
  "nightlyPrice": 303,
  "totalPrice": 2122,
  "fees": { "cleaning": null, "service": null, "taxes": null },   // null when the source doesn't itemize
  "nights": 7,
  "occupancy": { "adults": 2, "children": 2, "childAges": [8, 13] },
  "source": "booking",
  "url": "https://…"
}

PriceCompare

One property, many OTAs — plus first-class min and median computed by ScoutingAPI across every offer’s total.

PriceCompare
{
  "property": "Hotel X, Sibenik",
  "checkIn": "2026-07-13", "checkOut": "2026-07-20",
  "currency": "EUR",
  "min": 2122,       // ScoutingAPI-computed: lowest offer totalPrice; null if no offers
  "median": 2151,    // ScoutingAPI-computed: median of offer totalPrices; null if no offers
  "offers": [
    { "ota": "booking.com", "totalPrice": 2122, "currency": "EUR", "url": "…" },
    { "ota": "expedia", "totalPrice": 2180, "currency": "EUR", "url": "…" }
  ]
}

Review

Review
{
  "platform": "tripadvisor",
  "listingId": "d12345",
  "reviewId": "r987",
  "rating": 5, "ratingScale": 5,
  "title": "Perfect family stay",
  "text": "…",
  "author": "Jane D.", "date": "2026-05-10",
  "tripType": "family", "language": "en",
  "ownerResponse": "Thank you!",
  "liked": "…", "disliked": "…"
}

Rating scales are echoed, never rescaled

Amenity taxonomy

Every adapter maps a platform’s raw amenity terms onto one controlled, snake_case vocabulary. The amenities[] filter on search accepts only these tokens (an unknown token → 400 invalid_amenity). The set is additive — tolerate unknown tokens.

TokenMeaning
poolSwimming pool
hot_tubHot tub / jacuzzi
kitchenFull kitchen
wifiWireless internet
air_conditioningAir conditioning
heatingHeating
parking_freeFree parking
parking_paidPaid parking
pet_friendlyPets allowed
washerClothes washer
dryerClothes dryer
ev_chargerEV charging
gymGym / fitness
sea_viewSea / ocean view
beachfrontDirectly on the beach
balconyBalcony / terrace
bbqBBQ / grill
workspaceDedicated workspace
cribCrib / infant bed
elevatorElevator / lift
wheelchair_accessibleStep-free access
smoke_alarmSmoke alarm
breakfastBreakfast available
spaSpa / wellness
gardenGarden / green space
fireplaceIndoor fireplace
dishwasherDishwasher
self_check_inSelf check-in
non_smokingNon-smoking
family_friendlyFamily friendly

Airbnb amenity/pool filtering is post-filtered

Currency & localization

Pass-through, never FX

Default currency is USD. The effective currency is always echoed in meta.currency and in each price object. The currency parameter is a hint that triggers actor-side localization where supported; where it can’t localize, ScoutingAPI echoes the source currency unchanged and adds a currency_passthrough warning. No FX conversion is ever performed. On a mixed-currency fan-out, meta.currency echoes the requested currency and each item carries its own.

The unified schema types ship in @scoutingapi/schema and are re-exported by the SDK, so your types never drift from the API.