UCP Checker
UCP Lodging Is Merged: What Changed on the Way to the Spec

UCP Lodging Is Merged: What Changed on the Way to the Spec

On 24 September the Lodging Technical Council's PR #780 was merged into the Universal Commerce Protocol repository, and on 25 September the council announced it: dev.ucp.lodging.booking, plus a cancellation-policy extension, is now part of the spec as a draft.

It's the first capability from a vertical other than shopping to make it into the spec. Four weeks ago we read the PR as filed. This post covers what it looks like now, what changed in review, and what it still leaves to later.

What "merged" means here, and what it doesn't

The capability page opens with a banner:

This capability is in draft status. Implementers are cautioned that data models, protocol bindings, and operational flows are under active iteration and may undergo breaking changes as the specification evolves.

So be precise about where it stands:

  • In the spec repository: yes. Schemas, REST and MCP bindings, and docs are published at ucp.dev/draft.
  • In a release: no. The latest release is still v2026-08-25, which ships only dev.ucp.shopping.* and dev.ucp.common.*. Shopping Tech Council minutes target the next release for early December 2026 or January 2027. They don't say whether lodging will be in it.
  • Stable: no. Two design questions were explicitly deferred to issue #858, and one of them is about naming.

The merge is still a milestone. A vertical has gone from a charter (June), to a council (August), to a merged spec (September) in three months, and it did so by building on the shared common/ layer instead of writing its own.

What merged

Capability dev.ucp.lodging.booking
Extension dev.ucp.lodging.policy.cancellation
Operations create, get, update, complete and cancel_booking_session
Transports REST (OpenAPI) and MCP (OpenRPC)
Size 35 files, about 6,000 added lines
Reused from common/ payment terms, split payments, payment authentication (3DS), AP2 mandates, totals, policies, messages, actions
New in common/ a date_interval type and a totals_changed warning

The flow will be familiar to anyone who has implemented checkout. A platform opens a booking session using the property, stay, rate plan and dates it found upstream. It adds guest and payment details over one or more updates. When the session reaches ready_for_complete, it completes it to create a confirmed reservation. The status values match checkout's, including requires_escalation with a continue_url for handing off to a human.

The business stays merchant of record. It doesn't need to become PCI DSS compliant to accept cards this way. And unless the AP2 mandates extension is in play, the spec says the user finalises the booking in a trusted UI: the agent prepares the booking, and a person confirms it.

Five things that changed in review

The version that merged isn't the one filed on 28 August. The review was long and public, and some of what changed matters beyond lodging.

1. Rooms became stays

The filed draft talked about hotel rooms: room_rates[], room_details, itinerary. The merged schema is generic: a property, one or more stays[], each binding an accommodation_type, a rate_plan, stay_dates and occupancy. The compound binding we highlighted last time is still the heart of it; only the vocabulary moved away from hotels. The same schema can now describe a villa, a cabin or a campsite pitch as well as a hotel room.

It doesn't yet say which of those a stay is. Whether to add an explicit accommodation type, and how strict to make it, is the first question in #858. That issue's example is a hotel needing a check-in desk while a vacation rental needs lockbox details.

2. Totals mean price; payment terms mean timing

This is the most important change, and it came from reviewers checking the arithmetic. Early drafts gave lodging its own meaning for the total, the amount due now, with extra types for money due at the property and later. That clashed with UCP's shared totals type, where total is the grand total everywhere else: in cart, checkout and order. It also made a stay paid entirely at the property awkward to express.

The merged version separates the two questions. totals describes what the stay costs. When it's paid goes in payment terms: each term has schedules[], which can be immediate, deferred or at_property, and the schedules in the selected term MUST add up to the total. The total itself is the all-in cost of the stay, and the spec says the guest MUST see it before the booking is confirmed. A deposit today and the balance at check-in is now two schedule entries against one total, not two totals.

For anyone checking conformance, this is the best kind of rule: one a machine can verify.

3. Payment at completion, even when nothing is charged

payment is required when a booking completes. But for a pay-at-property or deferred reservation with no card guarantee, an empty payment: {} satisfies it. The payment term is chosen during update, not at completion, because choosing a term can change the price, and the price has to be settled before the session can be ready_for_complete.

4. Guests are private until the booking needs them

The booker, who contracts and pays, is still separate from the guests who stay. Guest IDs are minted by the platform, scoped to one booking session, and MUST NOT carry personal data or cross-merchant tracking identifiers. Businesses MUST NOT link guests across sessions. Platforms SHOULD NOT send guest identity beyond the ID until the booking reaches ready_for_complete, and then only the fields the business asks for. Guest roles are now primary and accompanying.

5. expires_at became a price-hold promise

The session's expires_at now covers "session state, quoted pricing, and any temporary inventory holds". Its description carries a rule we've wanted since our expiring-inventory study: businesses MUST NOT complete a booking at a changed price without first returning updated totals to the platform. It doesn't make agents check the clock, but a silent price change at completion is no longer allowed.

One thing that deliberately didn't change

Shopping names its tools with short verb-noun pairs like create_checkout and cancel_checkout. Lodging kept a _session suffix: create_booking_session, cancel_booking_session. The council's reason is agent safety. In hotels, "booking" means both a draft in progress and a confirmed reservation. A tool called cancel_booking invites an agent to confuse throwing away a draft with cancelling a non-refundable stay.

A reviewer asked for consistency with shopping. The council kept the suffix and moved the question to #858, where it will be settled before the naming is frozen. Anyone implementing now should expect these names might change.

What we said in May, and what the draft does

When Google opened its lodging waitlist in May, we listed what UCP for Lodging would need to specify and promised a side-by-side when the spec landed. Here it is against the merged draft:

We said it needed The merged draft
An offer that binds room type, rate plan, dates and occupancy Yes. A stay binds accommodation_type, rate_plan, stay_dates and occupancy.
An all-in total, taxes and fees included Yes. total is the all-in cost of the stay, and the guest must see it before confirming.
A clock on the offer In part. expires_at holds the quoted price inside a session. How long a rate from search stays valid is out of scope.
Re-validation before booking Yes. The session is authoritative, and a business can't complete at a changed price without returning updated totals first.
Machine-readable cancellation In part. Refundability is structured; cutoffs and penalties are still text.
Servicing: modify, cancel, no-show Not yet. Left to future post-purchase order extensions.
Identity, loyalty and payment timing Mostly. Deposits, balances and pay-at-property are payment-terms schedules. Identity linking and loyalty already exist in common/; the charter puts account linking and loyalty in Phase 1.5.

A spec can't answer one thing on that list: whether agents use what it gives them. Our expiring-inventory study found frontier models didn't check an offer's clock. expires_at gives them one to check. Whether they do is something we'll only see once live endpoints exist.

What it leaves for later

The draft is scoped as the booking core, and the PR says so. Out of scope:

  • Discovery and search. The session starts from rates found "upper-funnel". How a platform finds them isn't specified.
  • Offer binding and quote lifetimes before a session exists. A rate seen in search is provisional; only the booking session is authoritative. The council said in review that these are for later.
  • Managing a reservation after booking. Modifications, cancellations and check-in are left to future post-purchase order extensions.
  • Booking on behalf of someone else. Dedicated fields for travel agencies, or for occupants who aren't people, beyond the standard booker and guest.
  • Deterministic cancellation schedules. The extension classifies a policy as refundable, partially_refundable or non_refundable, with a description that MUST NOT contradict it. Cutoffs, penalty tiers and no-show outcomes are still text. A separate open proposal would make them structured. It was filed as #808 against the lodging branch and re-filed as #861 after the merge.

Disclosure: we're running an independent lab study of how agents handle cancellation terms, using test fixtures published by that proposal's author. This post takes no position on that proposal; it's the Lodging Technical Council's call.

Who built it

The announcement credits the Lodging Technical Council, whose inaugural members are Amadeus, Booking.com, Expedia, Google, Hilton, Marriott and Trip.com, along with open-source contributors. The review drew in reviewers from outside the council too: Shopify's Ilya Grigorik (per his GitHub profile) requested changes on 10 September and approved on 24 September, hours before the merge. A new vertical has to fit the shared spine, and this review is where that was worked out.

What this means if you build for lodging

  • Hotels and booking engines: there's now a concrete target to prototype against. Treat it as a draft: build against a pinned commit, keep your own namespace for anything the draft doesn't cover, and expect naming changes from #858. Getting totals right is the easiest thing to do now. Make sure your deposits and balances are schedules that add up to a total, not separate totals.
  • Agent builders: the _session names and the expires_at price rule are both there for your benefit. Take advantage of them. Re-read totals after every update, and treat a totals_changed warning as something to show the traveller, not to swallow.
  • Anyone building checkout-based lodging today: the council's answer in the review was direct: dev.ucp.shopping.checkout "holds no architectural promise or semantic support for lodging concepts". The lodging capability is where hotel bookings are meant to live.

What we'll do

We track the vertical on our UCP for Lodging page, which is updated for the merge. When a business first declares dev.ucp.lodging.booking in a live manifest, we'll say so. We'll validate declarations against the spec once it's in a release. Until then, a declaration is a declaration against a draft.

If you're shipping lodging endpoints early and want to know how they look from outside, run them through the validator.


About UCP Checker

UCP Checker is the independent validation and observability layer for the Universal Commerce Protocol. We crawl, validate and grade every public UCP manifest we can find, run the merchant directory, the UCP Score, live adoption stats, the vertical guides and the authority-bound vendor map, and track the spec as it evolves so you don't have to — measured from two vantages (what a business declares, and what actually happens when an agent transacts), the same way for everyone, without picking winners.

Sources

Check your domain's UCP status

See if your storefront is ready for agentic commerce in seconds.

Weekly UCP Report

Get the agentic commerce digest every Monday

Real adoption data, ecosystem trends, new spec versions, and the stores that broke or recovered this week. Read by founders and engineers building the next generation of commerce.

Free forever No spam Unsubscribe anytime

View a sample report →

Weekly UCP Report
Issue #51 · Sep 21, 2026
+664
new verified stores
Verified rate
Latest spec
Cart capability