Skip to main content
A reservation’s money lives in one or more folios. These findings come from rebuilding source folios on a destination property so that each balance matched the original.

What Cloudbeds charges automatically

When you create a reservation, Cloudbeds posts these itself. Don’t post them again:
  • Room charges, at the property’s current rate plan (see Rate differences).
  • Taxes and fees set up for the rate.
Commission was not posted automatically, even with a commissioned source mapped. While the booking was confirmed there was no commission line, and the folio was gross. See Commission.

Which endpoint does what

postCustomItem

POST https://api.cloudbeds.com/api/v1.2/postCustomItem. It took four live failures to get the format right:
  1. “Parameter items is required” → the items go in an items array, not as flat fields.
  2. “Invalid value given in ‘items’. Array expected.” → items must be PHP-form-encoded (items[0][itemName]=…), not a JSON string.
  3. “Parameter appItemID is required” → every item needs an appItemID.
What works:
  • Item fields: itemName, itemPrice (unit price), itemQuantity. Optional: itemSKU, itemCategoryName, itemNote, itemTaxes[], itemFees[].
  • appItemID is your own ID for the item type. A stable slug of the name works, so every “Food - The Grille” shares one.
  • referenceID makes the call idempotent: Cloudbeds rejects a second call with the same referenceID. Use one per reservation per pass.
  • Use the payments[] array rather than itemPaid, which forces the payment to cash.
  • Items are grouped under a category named after the API key’s name. You can route that category to a folio (see Two-folio bookings).

Copying charges from a source booking

The source’s guest-side charges split cleanly into two sets that don’t overlap:
  • Add-ons: getReservationInvoiceInformation → reservationAdditionalProducts.
  • Fees and surcharges: getTransactions lines with transactionType: "debit" and transactionCategory: "fee" (e.g. “Credit Card Surcharge”).
Net out voids: a +400 surcharge cancelled by a −400 line with transactionCategory: "void" and the same description should come to nothing. Skip deleted transactions. Together, add-ons plus fees matched what the guest paid to the cent on the bookings we checked. The room itself is an accommodation charge, which the destination generates on its own. Never post it.

Payments

  • Use the net paid amount (total − balance), not balanceDetailed.paid. paid is gross of refunds: one checked-out booking had total 14,366.06, paid 14,466.06 and balance 0, because of a $100 refund. Copying the gross figure overpays.
  • Post charges and payments before setting status, since checkout is refused while there’s a balance.

Two-folio bookings

Bookings from a billing agent source get two folios, Agent Main and Guest, through the property’s Folio Configuration. Typically the agent folio holds the room, on 30-day terms and often still owing, while the guest folio holds incidentals paid at departure. What we found (confirmed live):
  • Neither API version exposes the folios on a reservation. In v1.2, getReservationInvoiceInformation gives one combined invoice and a single sub-reservation. postCustomItem and postPayment take no folio ID. The v1.3 accounting API returned nothing for our property.
  • Charges can be routed by configuration. In Folio Configuration, route the API key’s item category (e.g. “Jason Imports”) → Guest Folio and “Room Related Charges” → Agent Main Folio. Charges then split correctly as they’re created, with no code change.
  • Payments can’t be routed. A payment goes on whichever folio you’re “in”. Through the API that’s the primary (agent) folio, whatever the configuration’s Credits section says. Nesting the payment in postCustomItem’s payments[] didn’t help either. An incidentals payment that belongs on the Guest folio has to be moved by hand after import. Flag those bookings for staff.
  • getTransactions doesn’t say which folio a line is on.
Check whether a booking has two folios from the source and the property’s folio configuration. Don’t guess from the amounts: about half our bookings were two-folio, and single-folio bookings can have incidentals too.

Commission

postAdjustment can post commission. An earlier conclusion that adjustments couldn’t be posted through the API was wrong.
  • type is one of rate, product, fee or tax.
  • A positive amount posts a reduction: 1 posts −1.00.
  • itemID must be the property’s internal product ID, not the SKU or item code (those return “Incorrect adjustment type”). The commission product doesn’t track stock, so getItems doesn’t return it. We found the ID by adding the product to one booking by hand and reading it back from getTransactions (the line’s originID). Ours was 1291044 on one property; it will differ elsewhere.
  • Find the source’s commission from its transactions: non-deleted lines with transactionCode C01 or the description “Hotel Commission”.
  • No referenceID, so posting twice posts twice. Only re-run on a fresh reservation.
  • Where it lands follows Folio Configuration: once the “Commission” category was routed to Agent, it landed on the Agent folio next to the room.

Rate differences

The destination charges the room at its current rate plan, not at what the source booking was sold for. In our migration that was often 1.3–2× higher. Find the gap from folio totals (destination total vs source total), not balances, so you catch it in both directions:
  • Over-charged (the usual case): reduce the room rate.
  • Under-charged: raise the rate, then post the rest of the payment. A balance check misses this case, because you’ve only paid the smaller destination total.
postAdjustment with type=rate and a positive amount (no itemID) should apply the reduction, and does so in the UI (“Adjust Charge → Room Rate”). That leaves the nightly room lines as they were plus one “Room Rate” reduction line. We confirmed it in the UI but didn’t run it through the API at scale; we fixed rates by hand. A booking whose room was comped at the source ($0 room) is still worth creating, because it holds the room. The destination charges full rate, so flag it loudly for manual correction.

postPayment has no idempotency, and nothing downstream notices

postCustomItem has referenceID; postPayment has no equivalent. Send the same payment twice and the folio carries it twice, which reads as a reconciliation that ran twice and settled twice — worse than one that never ran, because it looks correct. Two things that help:
  • Carry your own one-time claim before the call, keyed on something the caller cannot vary.
  • Refuse to post onto a folio with nothing outstanding, checked against the amount rather than against zero. They are the same rule: posting more than is outstanding overpays, and a zero balance is that with nothing left at all. A partially-paid booking is the case nothing else catches, because its total still agrees.

Reconciling against a partner’s statement

Findings from matching remittance files to Cloudbeds bookings.

Two different reference columns, and only one is on screen

A booking carries source_reservation_id (the source’s own reference, which is what the Cloudbeds UI shows) and third_party_identifier. They are not the same field and they are not always the same value. We met a mid-stay upgrade that Cloudbeds booked as a second reservation under the same agent reference: the two rows looked different in the UI, because the collision was on third_party_identifier, which is indexed and never displayed. If you join on a partner’s reference, join on all of them and report an ambiguity by name.

paymentCollect does not tell you who takes the money

It reads as collect for channels that take the guest’s money — but what several of those pass on is a virtual card the property charges, so the transaction goes through Cloudbeds’ own payments and lands in the payout like any other. Booking.com and Agoda/Priceline both behave this way. Deciding which bookings belong to a payout from this flag puts whole channels on the wrong side and manufactures findings in both directions.

A refunded booking’s folio is emptied, not left in credit

Where Cloudbeds payments reverses the guest’s card, the booking is cancelled and its folio zeroed — total 0.00, balance 0.00 — while the money still appears on the payout as a negative line. No figure the PMS carries equals the refunded amount, so a row like that can never balance against the folio however you widen the window. That emptiness is consistent with a refund, not proof of it: a comp, a stay not yet priced, and a folio billed elsewhere all look identical. We require the booking to be cancelled as well as empty before reading it that way. Other partners leave the credit on the folio instead, which is a figure you can compare — so this is a per-source behaviour, not a Cloudbeds-wide rule.

Compare on the right column, per partner

Some agents settle only what the guest has not paid. A guest who books through such an agent and then extends pays for the extra nights themselves, on the same reservation — so the folio comes to 203.95 while the agent remits 53.95. Those rows reconcile on the outstanding balance, not the stay’s total. Partners whose folios are settled at the point of sale read zero outstanding, and comparing those on balance would make every line differ. Pick the column per partner and say on screen which one you used.

The payout export is a legacy .xls

Cloudbeds payments’ export is an OLE2 compound file (BIFF8), not the ZIP-of-XML that .xlsx is. They share an extension and nothing else, so a reader for one will not open the other. Settlement runs about two days after checkout, which is why one booking can be funded across two payouts — and why a booking can be part-paid by a card payout and part-paid by an agent whose own run lands later.