Money and volume

Settlement modes

Who takes the traveller's money decides which price the API quotes you, so it is settled before you search, not while you book. It is a property of the key you call with. Today one of the two modes is built.

Only mode A is live

Every key issued today books in mode A: you are merchant of record, we quote you net rates, and the booking settles against your account. Mode B — we collect from the traveller — is described on this page because it is contracted and planned, but it is not callable. There is no checkoutUrl in any response. Do not build against it yet; this page and the changelog will say when it lands.

Where the mode comes from

The mode fixes the price: in mode A the API returns net rates, in mode B it returns the consumer price. The price is made at search time and the booking call comes later, so a mode chosen at booking time could not change the price it was supposed to govern. It therefore hangs on the key.

  • One key, one mode. Which modes your account may use is agreed in your contract; each key is issued for exactly one of them. Run both models side by side by holding two keys — searches under the mode-A key are priced net, searches under the mode-B key are priced retail.
  • Today. Do not put settlement in a booking body. Nothing reads it as an instruction, so at best it changes nothing and at worst the request validator refuses the whole request over an unknown property. Leave the field out and the key decides, which is what happens either way.
  • Planned. The field is to become an optional assertion on the booking body: send it and we check it against the key. A value that contradicts the key is a 400; a mode your account is not enabled for is a 403. It is a safety catch against calling with the wrong credential, never a way to pick the mode — and until the changelog announces it, do not rely on either the acceptance or the rejection.
POST /v1/hotels/bookings — send this, and no mode with it
{
  "rateId": "rate_8f2c…",
  "externalReference": "booking-2026-0915-abc",
  "guests": [ … ]
}

// The mode comes from the key that signs this call.
// There is no field here that can change it.

You can read the modes your account is enabled for off GET /v1/account, in settlementModes. Note that the field reports your contract, not what the endpoints do yet: an account listing vacabee today still books in mode A.

Side by side

This is the commercial shape of the two modes as contracted. The vacabee column describes what mode B will do, not what any endpoint does today.

partner — you collect (live)vacabee — we collect (planned)
Merchant of recordYouVacabee
Price the API returnsNet rate: our purchase price plus our agreed B2B marginConsumer price, including your own markup
Traveller paysYou, through your own checkoutVacabee, through a hosted checkout we return
Traveller's invoiceIssued by youIssued by Vacabee
You earnWhatever you add on top of the net rateA commission on your markup, paid out monthly
Chargeback riskYoursOurs
Security we holdYour prepaid balance, plus a credit limit if one was agreedTo be agreed — no reserve mechanism exists in the platform today
You owe usThe net rate per booking, drawn from your prepaid balance as the booking confirmsNothing — we net your commission out

The search and booking endpoints are the same routes in both modes. What changes is the amount in the price fields — there is no field called price; money is always a …Cents integer next to a currency, so it is totalCents on a rate or offer and totalAmountCents on a confirmed hotel booking — and what comes back from the booking call.

Mode A — you are merchant of record

This is what every key does today. Prices are net, you set your own retail price, you take the payment, and you owe us the net amount. Settlement runs against a current account we keep for you.

  • Funding. You fund the account up front by bank transfer, arranged with your Vacabee contact — there is no self-service top-up, no card and no SEPA direct debit today, and no deposit page in the portal. Quote the accountRef from GET /v1/account/ledger (scope ledger:read) and confirm the exact purpose line with your contact before you send a five-figure transfer; a payment that cannot be matched sits unattributed.
  • Available credit is availableCents = balanceCents + creditLimitCents. Holds are stored as negative entries, so money reserved for a booking in flight is already out of balanceCentsheldCents is shown so you can explain the number, not so you can subtract it again. A credit limit only exists if one was set on your account by hand; the default is zero, so in practice available credit is what you have paid in.
  • Two-phase booking. A booking places a hold against available credit before we go to the supplier. A confirmed booking converts the hold to a charge; a failed one releases it. A hold that is never resolved expires by itself, so a crashed request cannot silently block your credit. Every step is a line in GET /v1/account/ledger/entries: DEPOSIT, HOLD, RELEASE, CHARGE, REFUND, ADJUSTMENT.
  • Not enough credit is 402 insufficient_funds, before the supplier is contacted, and the error carries availableCents and requiredCents. There is no warning before it: ledger.low_balance can be subscribed to but nothing publishes it, and no threshold exists on the account. Poll GET /v1/account/ledger and alert on availableCents yourself — that is the only low-balance alarm there is.
  • Settlement. There are no settlement runs and no invoices for bookings today: a booking is charged against your prepaid balance at the moment it confirms, and the ledger is the record. Search fees are metered but not invoiced either, so nothing about searching appears on any bill at present.
  • A blocked account answers 403 account_not_active on bookings while searches keep working. It is an invoicing matter, not a key problem, and topping up does not clear it — talk to your contact. Note that the status field on GET /v1/account/ledger publishes ACTIVE, SUSPENDED and CLOSED, while the internal read-only state is not among them: branch on the 403 and its accountStatus detail rather than on the enum. Nothing notifies you when the state changes.

Net rates are confidential

Net rates are our purchase conditions. Your contract restricts what you may do with them, and the API is rate-limited against bulk price extraction. Show retail prices to travellers, not the net rate you received.

Mode B — we are merchant of record

Not available yet

Nothing in this section is callable. The booking endpoints do not return a checkoutUrl, there is no hosted checkout behind one, and no key books in mode B — including a key whose account lists vacabee in settlementModes. Building a payment flow around this response today means building around a field that does not arrive. The shape below is the intended design, published so you can plan; treat it as subject to change until the changelog says it is live.

The intent: a booking made with a mode-B key returns a hosted checkout link instead of a confirmed booking. You send the traveller there; we take the payment, issue their invoice, and confirm the booking. You are told through booking.confirmed.

One consequence worth planning for now, because it shapes your integration rather than just your error handling: the link holds a price for a defined window, not a reservation at the supplier. Nothing is held for the traveller while he decides. If the window passes before he pays, the booking is not made and you get booking.failed — expiry is the normal outcome of an abandoned checkout, not an error to escalate. You re-quote and issue a new link.

The design, as agreed — none of it is callable yet:

  • No deposit, no ledger hold, no credit check for a mode-B booking. Today every booking path takes a hold against your prepaid account, which is why a key contracted for vacabee still needs a funded balance.
  • Prices would include your markup, within the ceiling agreed in your contract. On the API today no partner markup is applied at all: search and booking prices carry our net margin only, so what you see is your cost, not a retail price.
  • Your commission is accrued when a booking confirms and matures after a clawback period. Two things to plan around: maturity is anchored on the travel date — hotel checkout, flight departure, first transfer pickup — plus the clawback days, not on the confirmation date, so a January booking for an August stay matures in August. And for bookings placed through the API in mode A no commission accrues at all, because you are the one earning the margin.
  • A refund reverses the accrued commission. Chargebacks are not handled anywhere in the platform today, in either direction — do not model them as automatic.
  • Traveller emails would come from us in mode B. There is no per-partner setting for their branding or for suppressing them today; if the traveller must never see the Vacabee name, raise it in your contract discussion rather than expecting a toggle.

Price drift

Supplier prices move between the moment you search and the moment you book. There is no contractual tolerance held on our side that catches that for you — the only ceiling that exists is one you send yourself, per request.

  • Flights. Airlines reprice an offer before ticketing as a rule, not as an exception. Send maxTotalCents on POST /v1/flights/orders: above it nothing is booked and nothing is charged, and you get 409 price_changed with previousTotalCents and currentTotalCents so you can decide or ask your traveller. Omit it and we book at the new price, whatever it is.
  • Hotels. There is no reprice check on the booking call and no field to cap it with. A rate is booked at the amount held against the rateId, and a rate whose window has passed is 410 offer_expired rather than a surprise price. Re-read the rate shortly before you book if the amount matters to your margin.
  • Transfers. Same as hotels: a quote is booked at its quoted amount, or it is expired.

Handle the 409 before you go live: it is the single most common source of post-launch disputes. There is no sandbox trigger that reproduces it — exercise the path against your own stub of the response. See sandbox.

NextWebhooksWhich events are delivered today, signature verification and retries.