Cloudbeds AI Voice Agent: Room Changes, Rates, Webhooks

On this page
Last verified November 5, 2026, against the Cloudbeds developer documentation pages linked below: Reservation FAQs, Example 4, tech specs, FAQ, webhooks, putReservation, getAvailableRoomTypes and postPayment. Behaviour is scoped to the API v1.2/v1.3 pages I opened. Cloudbeds can change it; check the changelog.
Your Cloudbeds AI voice agent answers the phone inside a hotel product. A guest says, "Can we move to something with a balcony?" The agent hears one sentence. Cloudbeds sees a room-type change, a repricing, possibly a balance and a handful of events. If the agent gets one step wrong, the reservation looks fine until check-in.
This post covers the Cloudbeds reservation API side of that call, for any AI phone agent for hotels. It stays on the API: what a room change does to rates and totals, how room types differ from rooms, availability, payments, rate limits and webhooks. For the property-system view of hotel agents in general, see our hotel PMS AI voice agent guide. For the series overview, start at AI voice agent integrations.
I only state Cloudbeds behaviour that I saw on a documentation page. Where the docs are silent, I say so. Treat every silence as a test case.
What a room move does in Cloudbeds
The Cloudbeds Reservation FAQs describe the mechanism in one section. The room type or stay dates change when you send new values in the `rooms` array of `putReservation`. Then the pricing "will be automatically adjusted to the current rate for the new room". To keep the old price, you need a separate call: "If you wish to override it, you need to send a /postAdjustment call to adjust the rate."
Read that twice. Three consequences follow for a voice agent.
1. The agent does not choose the new price. Cloudbeds does. The agent only learns the result by reading the reservation back.
2. "Current rate" is not "the rate you quoted". A caller who booked in March at a promo price moves rooms in October. The docs say the new price is the current rate for the new room. They do not say that the old discount follows the guest.
3. Honouring the old price is a second, separate write. If your policy says "no charge for upgrades we suggest", that is a `postAdjustment` call. A prompt that says "tell the guest there is no charge" does nothing to the folio.
The `putReservation` reference page I opened is thin. Its description reads "Updates a reservation, such as custom fields, estimated arrival time, room configuration and reservation status." It lists no parameters on the page text I could fetch. Build your request from the live reference, not from this post.
What the ledger looks like afterwards
Cloudbeds publishes a worked example, "Example 4: Update Accommodation Type". It uses a two-night reservation: one night in the original room and one night in a second room after the type change. Before the change, `getTransactions` returns 4 transactions: 2 room rates and 2 fees. After the room-type change it returns 8. The original four stay. In the Accounting Service sample on the page, void entries reverse the old room rate and fee, and new entries post for the new room.
That example is scoped to its own setup, and the page says to use the Accounting Service for properties that have moved to it, and the legacy `getTransactions` call otherwise. The lesson for testing holds either way: a room move leaves an audit trail of voids and new charges. A test that only checks the final total misses a wrong void.

Room types, rooms and what your Cloudbeds AI voice agent hears
Cloudbeds separates the accommodation type from the specific unit. Its webhook reference makes the split explicit with two events.
- `reservation/accommodation_type_changed`: "Notifies when the accommodation type (not unit) was changed on a reservation by the user or a third party."
- `reservation/accommodation_changed`: "Notifies when a reservation had any accommodation unit (e.g. room) reassignments."
Callers do not make this split. They say "a bigger room", "the one by the pool", "room 214 if it is free", "same kind of room, but quieter". Each maps to a different operation.
| What the caller says | What it probably means | Cloudbeds event to expect | What the docs say about price |
|---|---|---|---|
| "Upgrade us to a suite" | Different room type | accommodation_type_changed | Repriced to current rate for the new room |
| "Something with a balcony" | Type or feature, ambiguous | Depends on how the property models it | Ask which room type before writing |
| "Can we have 214 instead?" | Different unit, maybe same type | accommodation_changed | The pages I opened do not say whether price changes |
| "Add a night on the back end" | Date change | dates_changed | Same `rooms` array mechanism as type changes |
| "Move us to the other building" | Property-specific | Check your property setup | Not covered in the pages I opened |
The "price" column has a gap on purpose. The FAQ states repricing for a room type or date change. It does not state what a same-type unit swap does. Do not infer it. Run the test and record what your property does.

Why "balcony" is a trap
A phrase like "something with a balcony" is a feature, not an ID. Your agent has to resolve it to a room type the property actually sells. If your prompt lets the model guess a type name, it will sometimes name one that does not exist for those dates. Constrain the agent to the list returned for that property and those dates, and make it read the options back.
The same applies to spoken confirmation numbers. A reservation ID read over a noisy line is easy to mishear. Our alphanumeric capture post covers that failure. Cloudbeds says the `reservationID` "is generated by Cloudbeds and it is the unique identifier for a reservation", so a one-digit error points at a real, different booking.
Check availability before your Cloudbeds AI voice agent promises
The `getAvailableRoomTypes` page says it "Returns a list of room types with availability considering the informed parameters." The reference text I could open lists no parameters, so I cannot tell you which ones matter for guests, children or rates. Check the live page.
Two availability gotchas follow from other Cloudbeds pages.
Split reservations. The Reservation FAQs say split reservations "are created when there is no availability within one room type throughout the guest stay". They add: "In the API, we don't have a specific flag for split bookings." The same `subReservationID` is shared across rooms for non-matching stay periods. A guest asking to extend a stay might end up in two rooms. An agent that says "you are all set in the same room" after reading one sub-reservation will be wrong.
Availability moves while you talk. A caller takes two minutes to decide. Another channel can take the room in that gap. Read availability again immediately before the write, not once at the start of the call. Our integration testing post covers the check-then-act race in general.
Guest matching and payments
I could not open the Cloudbeds reference pages for guest lookup or `postGuest` this session. So I make no claim about how Cloudbeds matches or de-duplicates guests. That is itself a test: call twice from the same number, once with a spelled name and once with a nickname, and check whether you get one guest record or two. The wider hotel failures are in hotel AI reservation errors.
Payments I did open. The `postPayment` page says a payment can be applied to a reservation or to a house account. If you send both, only the reservation ID is taken into consideration. For a voice agent, that means a payment aimed at a master or house account can land on the reservation instead. Send one target, never both.
The Reservation FAQs also say `getReservation` includes `balance` (pending payment) and `paid` (amount already paid). Use those two fields as your post-condition. After a room upgrade and a collected difference, the balance should equal what you told the caller. If you take card details on the phone, read taking payments by phone and Stripe AI phone payments first.
Also remember `postReservation` does not apply promos or any rate plan. The FAQ says it "doesn't take into consideration any applicable rate plans or promos". A new booking made by voice can price differently from the same booking made on the website. That is a documented behaviour, so test it.
Cloudbeds API rate limit: two pages, two answers
Cloudbeds documents two different limits.
| Cloudbeds page | What it says |
|---|---|
| Tech specs | "10 requests per second" for all endpoints |
| FAQ | "Properties and Group Properties: 5 requests per second" and "Tech Partners: 10 requests per second" |
The pages disagree on who gets which number. The FAQ adds that "exceeding these limits may result in a temporary suspension of a user's API credentials." Neither page, as I opened them, says what the HTTP response looks like when you exceed the limit. Neither says whether the limit applies per property, per credential or per app. Ask Cloudbeds about the exact Cloudbeds API rate limit for your tier before you decide your architecture.
Worked example (illustrative numbers)
Assume a room-change call makes seven requests in a six-second burst around the write: read the reservation, check availability, `putReservation`, read it back, `postPayment`, read it again, and one fetch triggered by a webhook. That is 7 / 6 = 1.17 requests per second per call during the burst.
At 5 requests per second, four simultaneous bursts already use 4.7 rps. A fifth passes the limit. At 10 requests per second the limit arrives at about nine bursts. These numbers are assumptions, not Cloudbeds measurements. Count your own calls per flow.

A retry loop makes this worse. If your tool wrapper retries a throttled call three times, you triple the load at the worst moment. Our voice agent API rate limits post covers backoff and what to say to the caller while you wait.
Webhooks: useful, but not a source of truth
Cloudbeds offers webhooks for reservation changes. Its reservation events include `created`, `status_changed`, `dates_changed`, `accommodation_type_changed` and `accommodation_changed`. Several delivery rules matter to a voice agent.
- Your Cloudbeds webhooks endpoint must return a 2XX. Failed deliveries retry after one minute, up to five attempts.
- "Order of the events is not guaranteed." A `dates_changed` can arrive after the event that depends on it.
- "Duplicates will not be received." Cloudbeds says it does not send duplicates, but the same page lists other delivery caveats. Make handlers idempotent anyway.
- The page says a handler taking longer than two seconds can be treated as a timeout and resent.
- "Cloudbeds does not sign payloads, so this header is the supported way to authenticate deliveries." Use the auth header option when you subscribe.
- For `accommodation_type_changed`, the page says if several types changed, the payload shows only one. Fetch the reservation for the full picture.
For a Cloudbeds AI voice agent, the rule is simple. A webhook tells you something changed. It does not tell you the final state. After any event, read the reservation, then compare it with what the agent promised. Do not let a webhook handler text the guest a confirmation based on payload fields alone.
Webhooks also catch changes your agent did not make. A front desk user can move the same guest while your agent is mid-call. The event says "by the user or a third party", so your agent cannot assume it was the author.
Where room-change failures hide
Voice errors that look small on the phone become silent record errors in your Cloudbeds AI voice agent's bookings.
- Wrong room type heard. "Deluxe double" heard as "deluxe suite" reprices upward. The reservation is valid. The guest finds out at checkout.
- Price promised, ledger different. The agent says "no extra cost". Cloudbeds repriced to the current rate and nobody called `postAdjustment`.
- Confirmed before the write landed. The agent says "done" while the API call is still pending or failed. See voice agent post-call write-back testing.
- Event-driven message too early. A webhook fires and a handler sends a confirmation before the balance is paid.
- Partial change. The room moves but a payment fails. Now the reservation holds a new price and an unpaid balance. Our rollback actions post explains how to plan for that.
- Wrong scope. An agent with write access to every reservation can change a stranger's booking. See voice agent permissions.
These errors are all invisible in a transcript. The transcript says "Yes, I've upgraded you." The folio says otherwise. That is why we judge from the audio and the resulting state, not only from the text.
How to test a Cloudbeds AI voice agent's room-change call
Use a sandbox or a test property you control, never live inventory, to test your Cloudbeds AI voice agent.
1. List your room-change intents. Include type upgrade, type downgrade, same-type unit swap, date extension, date shortening and "I don't know what I want".
2. Create a test reservation per case with a known rate, a known balance and a known guest name.
3. Script the caller. Vary accent, pace, interruptions and background noise. Include a caller who changes their mind after hearing the price.
4. Run the call and record the audio. Capture each tool call the agent makes with its arguments.
5. Assert the pre-write read. The agent must read availability right before `putReservation`, not only at the start.
6. Assert the post-write state. Read the reservation. Compare room type, dates, `balance` and `paid` against the quote the agent gave.
7. Check the ledger. Count transactions before and after. For a type change expect voids plus new entries, as in Cloudbeds' Example 4 (verify for your property).
8. Check the events. Confirm the expected webhook arrives, and test a duplicate, a late and an out-of-order delivery against your handler.
9. Break it on purpose. Return a throttled response, a timeout and a failed payment. The agent must tell the truth and stop.
10. Re-run after every prompt or tool change. Every change ships to live callers otherwise.
Evalgent generates test scenarios from your agent's prompt and flows, then calls your agent over phone, SIP or WebRTC with caller profiles such as accent, pace, interruption level and noise. It judges from the audio as well as the transcript, so a mis-heard room type is caught at the source. Evalgent does not connect to Cloudbeds. You supply the state checks in steps 5 to 8, and the call results tell you which ones to run.
A simplified post-condition check
This Python sketch checks the result of a room move. It does not build the `putReservation` body, because I could not open its parameter list. Build `rooms_payload` from the live reference. The base URL and the form-encoded body come from the Cloudbeds tech specs page. Auth headers come from your own token flow.
import requests
BASE = "https://api.cloudbeds.com/api/v1.2" # per Cloudbeds tech specs page
def get_reservation(res_id, headers):
r = requests.get(f"{BASE}/getReservation",
params={"reservationID": res_id},
headers=headers, timeout=5)
r.raise_for_status()
return r.json()
def move_room(res_id, rooms_payload, headers, quoted_total):
before = get_reservation(res_id, headers)
# PUT bodies are form-encoded per the tech specs page.
r = requests.put(f"{BASE}/putReservation",
data={"reservationID": res_id, **rooms_payload},
headers=headers, timeout=5)
r.raise_for_status()
after = get_reservation(res_id, headers)
# Field paths below are placeholders: read them from the
# getReservation response for your property.
if abs(after["data"]["total"] - quoted_total) > 0.01:
raise RuntimeError("repriced differently from the quote")
return before, afterTreat `["data"]["total"]` as a placeholder. The Cloudbeds page names `balance` and `paid`, so check against those once you see a real response.
Prompt and tool design for the room-change flow
Keep policy out of the prompt where you can. A prompt can say "confirm the new total before writing". Code should enforce it.
- The tool refuses a write unless a fresh availability read exists for the same dates.
- The tool refuses to say "confirmed" until the read-back matches the quote.
- A price-difference threshold above your limit forces a human handoff.
- Payment targets are one ID, never two.
- Every write logs the reservation ID, the arguments and the read-back.
In production, push your recordings into monitoring. Evalgent's production call monitoring transcribes calls, maps them to scenarios and judges them. It flags tool-call failures, latency spikes and policy failures. A room-change call where the agent said "no charge" and the tool log shows no adjustment is exactly the pattern you want flagged.
Frequently asked questions
Does Cloudbeds change the price when a guest moves rooms?
Cloudbeds' Reservation FAQs say that changing the room type or stay dates through putReservation adjusts the pricing automatically to the current rate for the new room. To keep a different price, you send a separate postAdjustment call. The pages I opened do not say what a same-type room swap does, so test it.
What does the Cloudbeds putReservation call update?
The reference page describes it as updating a reservation, such as custom fields, estimated arrival time, room configuration and reservation status. The FAQ adds that status changes and room-type or date changes go through it. Read the live reference for exact parameters, because this post could not verify the parameter list.
What is the difference between a room type and a room in Cloudbeds?
Cloudbeds webhooks separate the two. accommodation_type_changed fires when the type, not the unit, changed. accommodation_changed fires when a reservation had any unit reassigned. A caller asking for a bigger room means a type change. A caller asking for room 214 means a unit change.
What are the Cloudbeds API rate limits?
The Cloudbeds tech specs page says 10 requests per second for all endpoints. The FAQ says 5 per second for properties and group properties and 10 per second for tech partners. The pages disagree. The FAQ warns that exceeding limits may suspend API credentials temporarily. Confirm your tier with Cloudbeds.
Does Cloudbeds sign webhook payloads?
No. Cloudbeds says it does not sign payloads. The supported way to authenticate deliveries is a custom header you set when you subscribe, using authHeaderName and authHeaderValue. Your endpoint should return 401 if the header is missing or wrong. It must return a 2XX to confirm success.
Can webhooks arrive out of order or twice?
Cloudbeds says event order is not guaranteed. It also says duplicates will not be received, but a slow handler over about two seconds can be treated as a timeout and resent. Make your handler idempotent, respond fast and read the reservation after each event before acting.
How should a voice agent collect payment after a room upgrade?
Read the reservation's balance and paid fields after the change, quote the difference, then post the payment to the reservation. The postPayment page says that if you supply both a reservation ID and a house account ID, only the reservation ID is considered. Re-read the balance afterwards and compare it with what you quoted.
How do I test a Cloudbeds AI voice agent safely?
Use a test property and scripted callers with varied accents, pace and noise. For each call assert availability was read before the write, the new total matches the quote, the ledger shows expected voids and new entries, and the right webhook arrived. Then inject throttling and payment failures. Repeat after every prompt change.
The bottom line
For a Cloudbeds AI voice agent, a room move is a repricing event with a ledger trail and webhooks, not a simple edit. Test the quote, the write, the read-back and the events together, because the transcript alone cannot show a wrong total.
Related Articles

How to automate voice agent testing: synthetic callers vs manual QA
Learn how ai test automation replaces manual QA for voice agents. Compare synthetic callers vs human testers, with a 5-step framework to scale without hiring.
Read more
AI Agent Testing vs Voice Agent Testing: What General Tools Miss for Voice
AI agent testing measures text outputs. Voice agent testing measures behaviour through an acoustic pipeline. Five failure categories general tools miss.
Read more