Flagship endpoint
Price compare
Cross-OTA price comparison for one property — the flagship endpoint.
/v1/price-compareCross-OTA price comparison for one property — the flagship endpoint.
Live calls are asynchronous — you poll for the result
stay_test_ key) and from live cache hits. A live (stay_live_) call that has to scrape returns HTTP 202 with a data.jobId instead of blocking. Poll GET /v1/jobs/{jobId} (always free) until data.status is completed, then read the payload below from data.result (not data); the reconstructed meta — credits, platformResults, warnings — sits at the top level. Jobs usually finish in tens of seconds but can run several minutes (240s+), so budget your wait. The @stayingapi/sdk auto-polls a 202 to completion and hands you this exact synchronous-looking envelope — the simplest way to consume the API. See the response envelope for all three shapes.Rate-shop one property in a single call. TWO MODES, one response shape. GOOGLE MODE (name / location / googleHotelId) resolves the property through the Google Hotels backbone — you need no ids, but coverage varies: some properties resolve to several OTA offers, others to a single aggregated-lowest offer (then offers has one entry, min equals median, and the entry may be a direct-supplier rate rather than an OTA). Read offers.length before presenting a google-mode result as a multi-platform comparison — the schema does not guarantee more than one. DIRECT MODE (listings=) removes that uncertainty: you supply 2-6 platform:listingId pairs you already know are the same property, and we run a real price call on each one in parallel, so you get exactly the platforms you asked for, each a live quote for your dates and occupancy. Both modes carry StayingAPI-computed min and median as first-class fields.
Parameters
| Parameter | Type | Required | Default | Notes |
|---|---|---|---|---|
listings | string[] | One of | — | DIRECT MODE. 2-6 comma-separated (or repeated) platform:listingId pairs for the SAME property, e.g. airbnb:12345,booking:co/casa-de-alba. Split on the FIRST colon, so a full listing URL works as the id. Mutually exclusive with name / location / googleHotelId. |
name | string | One of | — | GOOGLE MODE. Property name to resolve. |
googleHotelId | string | One of | — | GOOGLE MODE. Precise Google Hotels id. |
location | string | One of | — | GOOGLE MODE. Disambiguating place / "lat,lng". |
checkIn | date | Yes | — | YYYY-MM-DD; not in the past. |
checkOut | date | Yes | — | Must be after checkIn. |
adults | integer | No | 2 | ≥ 1. |
children | integer | No | 0 | ≥ 0. |
childAges[] | integer[] | No | — | Length must equal children. |
currency | string | No | USD | ISO-4217; pass-through + echo. |
Request & response
GET /v1/price-compare?name=Hotel%20X%20Sibenik&location=Sibenik,HR&checkIn=2026-07-13&checkOut=2026-07-20&adults=2¤cy=EUR
Host: api.stayingapi.com
Authorization: Bearer stay_live_…{
"data": {
"property": "Hotel X, Sibenik",
"checkIn": "2026-07-13",
"checkOut": "2026-07-20",
"currency": "EUR",
"min": 2122,
"median": 2151,
"offers": [
{ "ota": "booking.com", "totalPrice": 2122, "currency": "EUR", "url": "https://…" },
{ "ota": "expedia", "totalPrice": 2180, "currency": "EUR", "url": "https://…" }
]
},
"meta": {
"requestId": "req_pc…",
"platforms": ["google"],
"cached": false, "partial": false,
"creditsCharged": 30, "currency": "EUR", "pagination": null,
"platformResults": [
{ "platform": "google", "status": "ok", "creditsCharged": 22, "cached": false, "count": 1 }
],
"warnings": []
}
}Code samples
The same call in every language that matters — all returning the identical unified schema.
curl -sS "https://api.stayingapi.com/v1/price-compare?name=Hotel%20X%20Sibenik&location=Sibenik,HR&checkIn=2026-07-13&checkOut=2026-07-20¤cy=EUR" \
-H "Authorization: Bearer $STAYINGAPI_KEY"Try it
Run this endpoint against the deterministic sandbox right now — a real 200, zero credits, no sign-up. The credit cost of the equivalent live call is 30 credits, or the sum of the legs.
/v1/price-compareRuns against the deterministic Google Hotels sandbox fixture — a real 200, zero credits.
Run the call to see a live, deterministic sandbox response.
curl -sS "https://api.stayingapi.com/v1/price-compare" \
-H "Authorization: Bearer $STAYINGAPI_KEY"Workflows using this
Ready-made automations built on /v1/price-compare — an importable n8n workflow + a portable AI-agent skill each.
- Multi-source price comparison → cheapest-rate report — Compare one property across booking platforms and report the cheapest rate, with savings vs. the median.
- Price-drop watcher — Watch a specific stay and get alerted the moment its total price falls to or below your threshold.
- Cross-OTA rate-parity monitor → parity-exception digest — Watch how your own listing's rate shows across OTAs on a schedule and flag any platform underselling the market median.
- Agent-native scouting via MCP — Connect StayingAPI as a Claude/Cursor MCP connector and scout stays, compare prices and check availability conversationally — no keys pasted.
- Booking-ready cheapest-link resolver — Resolve a property + dates to the single cheapest bookable link (with price and OTA) as clean JSON — for a concierge bot, a "book now" button, or an internal tool.
- Event / peak-date demand radar — Watch supply and prices around an event or peak date-window in a city and get alerted when demand tightens.
Notes & gotchas
Which mode should I use?
Fee coverage is uneven — compare on totalPrice
A partial comparison is still a 200
min & median are computed for you