Changelog

Changes to Beacon's APIs, and important changes to these docs, newest first.

In short

This page lists what has changed in Beacon's APIs, newest first. Most recent changes add information to rates and properties, such as meal plans, how flexible a rate is, cancellation deadlines and property details. Lighthouse-compatible API users should read the 14 October entries, which change what some answers contain. Each entry ends with what, if anything, you need to do.

How entries are written

  • Each entry has a date and a line of tags saying which API it affects: Rate Capture API, Lighthouse-compatible API, or both.
  • An entry that could stop working code from working is also tagged Breaking.
  • Each entry has two parts: What's changing and What you need to do.

Which changes count as breaking is on Versioning and changes.

16 October 2026: Members-only preview prices are flagged, and rate details are clearer

What's changing

  • geniusPrice is true when a Genius member discount applies to a Booking.com rate. Where the rate has a members-only price, price is that member price, originalPrice holds the public price and bar=true leaves the rate out. Otherwise price is the public price and bar=true keeps the rate.
  • originalPrice is null on Booking.com rates with no higher earlier price.
  • Some Premier Inn rooms have a derived price. They are real, bookable rooms, and conditions says "Derived price".
  • roomsLeft depends on the source. Travelodge gives 1 to 5, and a higher count is null. Booking.com gives the count the site shows. Premier Inn gives the site's own count, often large.
  • cheapestOfDay is true on every row tied at the lowest price.
  • A Booking.com rate refundable through Booking.com rather than the hotel has flexibility flexible and a deadline, but freeCancellation is false.
  • In the Lighthouse-compatible API cityTaxIncl is true on every Premier Inn rate. profile.cityTaxIncluded is per hotel, and false where the hotel has no city tax.
  • profile.city is filled for Premier Inn as well as Booking.com and Travelodge.
  • A Booking.com deadline with no stated time gives cancellationDeadlineTime 00:00, so free cancellation ends when that day starts.
  • reschedulable is true on Premier Inn Flex and Semi-Flex rates.
  • The persons filter on GET /v1/runs/{id}/rates drops rooms for fewer guests than persons.

What you need to do

Nothing. No field is added or removed. To compare public prices only, use bar=true, which leaves out members-only preview prices.

15 October 2026: Flexibility on every rate, cancellation deadlines, and a live shop

What's changing

  • Every rate in GET /v1/runs/{id}/rates and every row in GET /v1/runs/{id}/results has two new fields after cancellationDeadlineTime: flexibility and reschedulable.
  • flexibility is flexible, semi_flexible or non_flexible, or null when Beacon can't tell. It doesn't change freeCancellation or nonRefundable.
  • reschedulable is true when the booking can be moved to other dates and false when it can't. A rate that doesn't say it can be moved is false, so it is null only where there is no rate. It is filled for all three sources. A change fee still counts as reschedulable.
  • cancellationDeadline and cancellationDeadlineTime are now filled for Booking.com and Premier Inn as well as Travelodge, where the rate has a free-cancellation deadline.
  • The time is HH:MM, such as 18:00 or 12:00 for midday, on all three sources. It is null when only a date is known. Travelodge's non-refundable rates have no deadline.
  • On Booking.com, a rate that can be cancelled only at a cost has flexibility non_flexible, and nonRefundable is false. A rate refundable through Booking.com rather than the hotel has flexible with the deadline, and freeCancellation is false.
  • The CSV download of a report has a new column group, Flexibility, with four columns: Flexibility (Flexible, Semi-flexible or Non-flexible), Cancellation deadline (YYYY-MM-DD), Deadline time (HH:MM) and Reschedulable (Y or N). It is on by default, like every other group, so a CSV that doesn't name a groups list has all 24 columns. Untick it in the download options, or leave flexibility out of the groups list, to drop it.
  • Travelodge maxOccupancy (and occupancy on result rows) is now the room's own capacity. A Family room, Super Double Double or SuperRoom Double Plus now gives 3 or 4 instead of 1. These rooms are included when you filter for two or more persons, so a Family room can become a property's cheapest row.
  • profile.brand is now filled for all three sources: Premier Inn's code (PI, PID, HUB or the new ZIP), Travelodge or Travelodge PLUS for Travelodge, and the brand Booking.com lists, such as Hilton Hotels & Resorts.
  • profile.checkInFrom and profile.checkOutUntil are now filled for Premier Inn and Travelodge as well as Booking.com. profile.checkInUntil and profile.checkOutFrom stay Booking.com only. The review score and its reviewScale are unchanged: the site's own score, out of 10 for Booking.com and out of 5 for Travelodge and Premier Inn.
  • Lighthouse-compatible API: a live shop. POST /lighthouse/v3/liveupdate starts a fresh run of a subscription, and GET /lighthouse/v3/liveupdate/{id} says how far it has got. It needs a write key and charges credits exactly as POST /v1/runs does. See Live shop.

What you need to do

Nothing. On /v1 the change only adds fields, and none of the existing ones change. Read the new fields if you want them, and treat null as "not known". If your client rejects fields it doesn't know, allow these. If you use a Lighthouse client, it may now start live shops.

14 October 2026: More data on each rate and each property

What's changing

  • Every rate in GET /v1/runs/{id}/rates and every row in GET /v1/runs/{id}/results has two new fields after the last one: cancellationDeadline and cancellationDeadlineTime, the last date and the time of day that the rate can be cancelled free. Travelodge fills both. Anything the source doesn't give is null. The 15 October 2026 entry adds more fields and fills them for Booking.com and Premier Inn too.
  • Each property in a report document has a new profile: stars, review score, count and scale, latitude and longitude, city, postcode, country, property type, brand, check-in and check-out times, breakfast price, whether city tax is included, facilities, and when it was last seen. Which source fills which field is in the field dictionary. profile is null until the property has been captured.
  • Lighthouse-compatible API: stars is filled where it is known, for the hotel and its competitors. brand_code is filled for Premier Inn hotels (PI, PID or HUB). cityTaxIncl is true on Premier Inn rates. The rest stay as they were.

What you need to do

Nothing. The change only adds fields, and none of the existing ones change. Read the new fields if you want them, and treat null as "not known". If your client rejects fields it doesn't know, allow these.

14 October 2026: Lighthouse-compatible API matches Lighthouse more closely

What's changing

  • A date with no rate now has Lighthouse's empties instead of null: value 0, cancellable and best_flex false, roomName and roomType empty text, mealTypeIncluded 0, and maxPersons the persons you asked for. A priced rate has message empty text instead of null. extractDateTime is never null. Only the three tax flags are null.
  • los goes up to 45. compsetIds takes a list such as -1,1. ota=branddotcom covers the Travelodge and Premier Inn sites.
  • A currency other than the subscription's now answers 400. It was ignored. currency on each rate is the currency of the chosen rate.
  • best_flex is judged within the room type on room type rates and with a roomType filter. With shopLength, dates outside the run give general.missing records. A minimum stay with no number of nights is now general.missing. rates.restrictionlosN is Lighthouse's code.
  • /hotels is paged only when you send page, and meta comes only with a page. A page past the end answers 400. supported_search_types is gone from subscribed_features. The hotels CSV has Lighthouse's 10 columns, one row for each competitor.
  • Errors carry an errors list beside message, with status, code, title and detail. Answers carry X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset.
  • A path outside /lighthouse/v3/ now answers 404 with the code endpoint_not_found. A trailing slash on a supported path is accepted. Unsupported v3 endpoints still answer 501.

What you need to do

If you read null for a missing rate, check message instead. Send the subscription's own currency, or none. If you page /hotels, treat a missing meta as one unpaged list. The differences that remain are listed in Differences from Lighthouse.

14 October 2026: Lighthouse room types and a new message for a missing room type

What's changing

  • Lighthouse-compatible rates and room type rates: roomType now uses Lighthouse's values: parkandfly, dormitory, sharedbathroom, camper, villa, bungalow, suite, apartment, family, premium, budget, single and standard. Beacon classifies them from the room's name, so they can differ from the ones Lighthouse sets in its app. The roomType filter takes the same list, and the old values studio, triple, twin and double now answer 400 there.
  • Rate Capture API: roomType keeps its own values: suite, apartment, studio, family, triple, twin, double, single, dormitory and standard.
  • Both APIs now classify room types more accurately from the room's name, so some rooms change type.
  • A roomType filter that matches no rate on a date now gives the message rates.roomtypes.unavailable. It was general.missing.

What you need to do

If you use the Lighthouse-compatible endpoints, check any code that reads or sends roomType, and stop sending the four old values. In both APIs, handle rates.roomtypes.unavailable wherever you handled general.missing for a room type filter.

13 October 2026: Meal plan words in the export, and no Breakfast included column

What's changing

  • The Meal plan column of the export file uses plainer words: breakfast is "Breakfast only", dinner is "Dinner only", lunch is "Lunch only", lunch_dinner is "Lunch + dinner" and breakfast_lunch is "Breakfast + lunch"; the other words are unchanged.
  • The export file no longer has a Breakfast included column; the rate plan group now starts with Meal plan. The API field breakfastIncluded is unchanged.

What you need to do

Code that reads the export by column name keeps working. Code that reads it by position must shift: everything from Meal plan on moves one column left, and the words in that column change as above.

13 October 2026: Lighthouse codes for lunch and dinner rates

What's changing

  • Lighthouse-compatible rates: a lunch_dinner rate is reported as mealTypeIncluded 2 (two meals = half board), and a dinner or lunch rate as 0 (Lighthouse's "no meal type included"), for Lighthouse compatibility only. A mealType=2 filter still means exactly half board, and mealType=0 still means any. It is null when there is no rate.

What you need to do

Nothing for code that ignores values it doesn't know. If your code treats 0 as 'no meal plan', a dinner-only or lunch-only rate now shows up there.

12 October 2026: Meal plans on every rate

What's changing

  • Every rate now has a mealType: room_only, breakfast, half_board, full_board, all_inclusive, breakfast_lunch, lunch_dinner, dinner or lunch. It is on the rows from GET /v1/runs/{id}/results and the rates from GET /v1/runs/{id}/rates, right after breakfastIncluded. The export file has a matching Meal plan column.
  • The mealType filter accepts those names, and any (the default), as well as the old codes 0 to 5. A name keeps only rates of exactly that meal plan: room_only no longer includes half board, full board or all-inclusive rates.
  • The filters.mealType echo in the rates answer is now a string, such as "any". It was the number 0. A request that sends mealType=5 gets "room_only" back.
  • breakfastIncluded is unchanged. A half board or full board rate shows it as false, so read mealType for the meal plan.
  • Lighthouse-compatible rates: mealTypeIncluded can now be 2 half board, 3 full board or 4 all inclusive, as well as 1 and 5. A breakfast and lunch rate is reported as 2 for compatibility, because Lighthouse has no lunch category. It is null when there is no rate. A date with none of the plan you asked for answers rates.meal.missing.N with the code you sent; in the Rate Capture API the message ends in the mealType name instead, such as rates.meal.missing.half_board.

What you need to do

Nothing for code that ignores fields it doesn't know. If your code reads filters.mealType as a number, read it as a string. If you filter with mealType=5 and want half board, full board and all-inclusive rates too, use any instead.

6 October 2026: Choose a run's time zone

What's changing

  • POST /v1/runs and POST /v1/reports/{id}/runs take an optional timeZone, an IANA time zone name such as Europe/Berlin. The run's 365 check-in dates start on today's date in that time zone, and dates that have passed are judged by the same zone's date.
  • Without timeZone, a run uses your company's time zone. That is Europe/London unless someone in your company has changed it in the web app.
  • POST /v1/reports/{id}/runs now takes an optional body, with timeZone as its one field.
  • Every run in an answer now has timeZone: the time zone the run used.
  • A name that isn't in the IANA list answers 422 validation_failed, with the problem in details.timeZone.
  • All other times and dates, such as startedAt and the from and to filters, stay UTC.

What you need to do

Nothing. A run started without timeZone uses your company's time zone. Send timeZone if a run's dates should start on the date somewhere else. Code that ignores fields it doesn't know keeps working.

5 October 2026: Times and dates are UTC, keys can expire, limits per company

What's changing

  • The from and to filters on GET /v1/runs are UTC dates, compared with the UTC date of each run's startedAt.
  • A key can be given an expiry when it is created: never, or after 1, 7, 30 or 90 days. A key with an expiry stops working at 23:59:59 UTC on its last day, and then answers 401 key_expired. See expiry.
  • Limits are set for each company. The figures on Limits are the defaults, and the web app shows your company's own figures under Company > API.

What you need to do

If you filter runs with from or to, send UTC dates. Nothing else changes for code that works today.