Recipes/Map a micro-market and watch it move
Code Feed20 min

Map a micro-market and watch it move

A guest choosing your hotel is not choosing between every hotel in the city. They are choosing between the dozen in your district, at their dates, in their price band. That is the market that decides your occupancy, and Booking already ranks it every day — you just have to store it and read it back.

Map a micro-market and watch it move

What you'll build

A command-line tool that turns a stored location search into the full picture of a micro-market: every listed hotel with its price, its position in Booking’s own ranking, its score and its distance to public transport, plus medians by star category. Point it at two dates and it reports the turnover — who entered the listing, who disappeared, who cut price and who climbed. Exports a shareable HTML report and a CSV.

Set this up first

Required

The endpoints don't take free text — they take your identifiers. This recipe assumes the things below already exist on your account; while one of them is missing the call answers empty, not with an error. Each point links to the recipe that walks it.

  1. 01

    Create the location search

    A destination plus its filters — stars, board, distance, occupancy. Those filters are the entity: they decide which hotels the market covers and what every run costs.

    Guide: Register the four entity types on your account →
  2. 02

    Run one import on the location search

    A Feed dataset only contains what an import has written. Point the feed at the search, launch the first run by hand and read the credit estimate before you press — the filters decide how many hotels it covers.

    Guide: Track the whole hotel market of a destination →

The same thing over the API, if you would rather not click:

cURL
curl -X POST "https://api.veetal.app/v2/account/location-search" \
  -H "veetal-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'   # see the account reference for the body

To see whether an import has already finished, list them:

cURL
curl "https://api.veetal.app/v2/account/imports" \
  -H "veetal-api-key: YOUR_API_KEY"

Feed reads are not billed per request. The credits go on the imports that collect the data, which is why the estimate appears before you launch and not after.

How it works

  1. 01

    Configure the market in the dashboard

    A location search is the market definition: destination, nights, occupancy and the filters that matter — stars, accommodation type, minimum score, distance from the centre. A district gives you a comp set; a whole city gives you a report nobody reads.

  2. 02

    Schedule it, then let it run

    The value is in the series, not in one snapshot. A daily schedule turns the feed into a record of how the market moved; the first extraction is just day one.

  3. 03

    Clone the recipe and add your key

    Node 20 and no dependencies. Your key goes in a `.env` file and never leaves your machine.

  4. 04

    Ask which dates have data, then read them

    The feed indexes by the check-in date each import searched, and history needs the import id that wrote it. `--dates` lists the valid pairs so you never guess.

  5. 05

    Diff two days

    Pass `--vs` with an earlier date. The turnover — who is listed today that was not there last week — is the signal nobody else is reading.

The call

One request returns every accommodation stored for that market and date, with price, stars, score, review count and location detail. The import id is what unlocks any day that is not the most recent one.

cURL
# The date is the check-in date the import searched. Older days need their import_id.
curl "https://api.veetal.app/v2/feed/location-search/YOUR_LOCATION_SEARCH_ID/2026-08-19/booking-location-search?limit=100&import_id=YOUR_IMPORT_ID" \
  -H "veetal-api-key: YOUR_API_KEY"

Clone and run

Runnable

The whole recipe is one self-contained folder: Node 20, no build step, and a test suite that runs without a key.

Terminal
git clone https://github.com/Veetal-Connect/recipes.git
cd recipes/micro-market-monitor
cp .env.example .env          # put your VEETAL_API_KEY in it
node --env-file=.env index.mjs --list
node --env-file=.env index.mjs YOUR_SEARCH_ID YYYY-MM-DD --vs YYYY-MM-DD   # the day to read, and the day to diff it against
View the repository ↗ Stack: Node 20 · JavaScript · no dependencies

Check your key first

One call, five seconds. If this answers, the recipe will run.

cURL
# The date is the check-in date the import searched. Older days need their import_id.
curl "https://api.veetal.app/v2/feed/location-search/YOUR_LOCATION_SEARCH_ID/2026-08-19/booking-location-search?limit=100&import_id=YOUR_IMPORT_ID" \
  -H "veetal-api-key: YOUR_API_KEY"

Questions

Why does a date I know was imported return 404?

Two reasons, and both answer with the same error 510. Either the date is not the one the import searched — it stores the check-in date, which for a daily schedule is the day it ran, not a date you pick — or you asked for an older day without its `import_id`. Without that id the endpoint only serves the latest extraction. Run `--dates` and use a pair from that list.

Is this the same as tracking my competitors?

It is the layer above. A comp set is the five hotels you chose; a micro-market is everyone Booking actually shows for those dates and filters, including the ones you never think about and the new opening that took your bookings last month.

What does it cost?

Reading the feed is not billed per request. The credits go on the imports that collect the data, and a location search is billed per extraction — check the estimate in the dashboard before you set a daily schedule on twenty markets.

Why does a hotel disappear from one day to the next?

Usually because it sold out for those dates, or closed its Booking inventory. That is the useful part: a hotel leaving the listing is a demand signal, and it arrives before it shows up in anyone's rate shopper.

Can I compare a whole city?

Yes, but page for it. A district returned ten hotels; a city returns hundreds and the response is paginated. The recipe walks every page — if you write your own, `pagination.hasMore` is the field that decides whether you are looking at the market or at a slice of it.

Are the prices comparable between hotels?

Within one extraction, yes: same dates, same occupancy, same moment. Note that `priceFinal` is what is charged after discount, and `priceOriginal` can be far higher — a headline rate of 583 dropping to 386 is ordinary, so averaging the wrong field will mislead you.

Build your own

Start free with 100 API credits. No credit card, no sales call.

Whatsapp