Path A — Use our search#
We hold the index. You search it live, show what comes back, and price whatever the customer picks.
Nothing to sync, nothing to keep fresh, and no storage to operate. This is the right default — see choosing a path if you are not sure.
Three endpoints:
POST /v1/listings/search | Find inventory |
GET /v1/filters | The facets your channel exposes |
GET /v1/listings/{listingId} | One listing in full, for a detail page |
Searching#
Every field is optional. An empty body returns the first page of everything on your channel, which is a reasonable "browse all" landing state.
Filters combine with AND. Supplying dates narrows to what is actually available for them, so a search with checkIn/checkOut is the one to drive a results page from.
An empty data array is a successful search with no matches — not a 404.
curl -X POST "$BASE/v1/listings/search" \
-u "$ELIVAAS_API_KEY:" \
-H 'Content-Type: application/json' \
-d '{
"city": "Kasauli",
"adults": 4,
"checkIn": "2026-08-10",
"checkOut": "2026-08-13",
"size": 20
}'const res = await fetch(`${BASE}/v1/listings/search`, {
method: 'POST',
headers: {Authorization: auth, 'Content-Type': 'application/json'},
body: JSON.stringify({city: 'Kasauli', adults: 4, size: 20}),
});
const {data, nextCursor} = await res.json();{
"data": [
{
"id": "lst_0853ie",
"title": "Querencia | Pet-friendly 5-BHK Villa",
"city": "Kasauli",
"state": "Himachal Pradesh",
"maxAdults": 13,
"price": 2955300
}
],
"nextCursor": null
}Paging results#
nextCursor comes back whenever the page was full, and is null on the last page.
Loop until it is null. Do not stop when a page returns fewer rows than size — that is not the end-of-data signal, and treating it as one silently truncates your results.
Filters#
GET /v1/filters returns the filter bar for your channel: the facets, their labels and their permitted values.
Drive your UI from it rather than hardcoding a list. Facets differ per channel and change over time, and a hardcoded value your channel does not carry produces an empty result set with no explanation — which reads to a customer as "you have nothing", not "that filter does not exist here".
curl "$BASE/v1/filters" -u "$ELIVAAS_API_KEY:"A detail page#
GET /v1/listings/{listingId} returns one listing in full — everything a detail page needs.
For dates and prices on that page, call GET /v1/availability and GET /v1/rates for the one listing. Both are documented on the sync page because that is where they are used in bulk, but they work perfectly well for a single listing.
Promotions#
GET /v1/promotions lists promotions running on given listings, optionally as at a date (activeOn).
Keeping the request count sane#
One search per keystroke will hit the rate limit. Debounce a type-ahead, and use POST /v1/orders/preview — not a fresh order — for a price that updates as someone changes dates.
If you find yourself calling search in a loop to build a local copy of the catalogue, you want Path B instead. Search is for discovery; it is not a sync mechanism.
Next#
You have found something to sell. Price it.