Docs/Channels/Booking.com

Update Booking.com Pricing

Set Booking.com rates per room and rate plan, at an explicit occupancy, with length-of-stay and arrival restrictions sent in the same call. For a nightly price on every connected channel at once, use PUT /v1/availability/{propertyId} instead.

PUT/v1/channels/booking/availability

Parameters

typestringRequired

rates | availability | derived-pricing

property_idstring | integerRequired

Booking.com property id, connected to your workspace.

updatesarrayRequired

For rates: { roomId, rateId, dateRange: { start, end }, price, currency, occupancy?, restrictions? } per item. Get roomId / rateId from GET /v1/channels/booking/properties/{id}/rooms.

verifyboolean

Read the dates back from Booking.com after the write and report whether the pushed prices are live. Defaults to true; false returns as soon as Booking.com acknowledges and reports applied: "unverified".

Occupancy is part of the price

Booking.com does not store "the price of this night". It stores a price for a night at a party size — the occupancy — on one rate plan. So occupancy is a key, not a preference: it decides which price you are overwriting. Every rate amount goes out with one.

  • Send an occupancy above the maximum the rate plan itself prices at, and Booking.com accepts the request but declines the amount without saying so. The night keeps whatever it held before — often 0.00 — and the acknowledgement looks identical to a successful write.
  • Send an occupancy below it and Booking.com answers 400. The published price does not change.
  • Omit occupancy and it is resolved from Booking.com's own data for that (room, rate plan) pair. The response echoes both the value used and where it came from: occupancy[].value, with occupancy[].source of request, rate_plan or room.
  • When it cannot be resolved for a pair, the write is refused with 422 naming updates[0].occupancy. A rate amount is never sent blind.
  • The guest capacity on your own listing is not an input. The number that governs is the one Booking.com holds for the rate plan — read it from GET /v1/channels/booking/properties/{id}/rooms.

Dates are inclusive at both ends

dateRange.start and dateRange.end are both nights that get written — on rates, on availability and on restrictions alike. To price a single night, send the same date twice. An end set one day past the last night you meant to touch re-prices a night you did not intend to.

# One night — 2026-11-04
"dateRange": { "start": "2026-11-04", "end": "2026-11-04" }

# Four nights — 2026-11-04, 2026-11-05, 2026-11-06 and 2026-11-07
"dateRange": { "start": "2026-11-04", "end": "2026-11-07" }

Inventory is a separate write

A rates update carries prices and restrictions only. roomsToSell sent on one is refused with 422 inventory_not_in_rate_update, naming updates[0].roomsToSell, and nothing is pushed.

  • Rooms to sell and the stop-sell flag belong to type: "availability" on this same endpoint, as availableRooms and closed. See Push Availability to Booking.com.
  • The two writes are independent. Pricing a night does not open it for sale, and opening it does not price it.

Whether the price actually landed

Booking.com usually answers a rate write with a bare acknowledgement that carries no per-date status — the body is literally {"ok": ""}. That is a receipt for the request, not a confirmation of the price, and it is no longer reported as "all updates applied". applied says which of four things happened:

  • verified — the dates were read back from Booking.com and every pushed price is live.
  • unverified — Booking.com acknowledged the write and the read-back was skipped or unavailable. This is an unknown, not a failure: the price may well be live, but nothing here proves it.
  • mismatch — the read-back shows at least one date that did not take the pushed price. verification.dates names them, with what Booking.com holds instead. An occupancy the rate plan does not price at is the usual cause.
  • rejected — Booking.com returned errors. errors[] carries them and nothing was published.

The read-back

Booking.com applies a write asynchronously, so the read-back waits a short settle delay before asking for the same dates again. It costs one extra Booking.com read per call.

  • Send "verify": false to skip it — useful for a long backfill you intend to reconcile separately. The call then returns as soon as Booking.com acknowledges, and reports applied: "unverified".
  • A skipped or unavailable read-back never reports verified. verification carries the reason it did not run.
  • Reconcile at any time with GET /v1/channels/booking/availability?property_id=1234567&start_date=2026-11-04&number_of_days=1.

Notes

  • Scoped to your workspace: a Booking.com property id that is not connected to your workspace returns 404 not_found, the same answer as an id that does not exist.
  • restrictions accepts minStay, maxStay, minStayArrival, maxStayArrival, closedToArrival and closedToDeparture. Omit a field to leave that restriction unchanged. exactStayArrival, minAdvanceRes and maxAdvanceRes are refused with 422 restriction_not_supported — Booking.com has no way to receive them, and they are refused rather than silently dropped.
  • A price and a restriction are two writes on Booking.com's side, so the response reports them separately in price and restrictions. applied is partial when one lands and the other does not — that is a 200, not an error, and restrictions.rejection.message carries Booking.com's own reason. See Minimum Stay & Restrictions.
  • The affected nights are read back off Booking.com after the write, so applied says verified or mismatch rather than echoing an acknowledgement. Send verify: false to skip it; applied is then unverified.
  • A rate amount is written against a party size. Send occupancy, or omit it and Repull resolves it from Booking.com's own data and echoes it back in occupancy[].
  • A listing-keyed equivalent is GET / PUT /v1/channels/booking/listings/{id}/pricing, which takes the Repull listing id.

Example

# One night, priced for a party of four
curl -X PUT https://api.repull.dev/v1/channels/booking/availability \
  -H "Authorization: Bearer sk_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "rates",
    "property_id": "1234567",
    "updates": [
      {
        "roomId": "123456701",
        "rateId": "98765",
        "dateRange": { "start": "2026-11-04", "end": "2026-11-04" },
        "price": 180,
        "currency": "USD",
        "occupancy": 4
      }
    ]
  }'

# Seven nights at a 2-night minimum, with the occupancy resolved from the rate plan
curl -X PUT https://api.repull.dev/v1/channels/booking/availability \
  -H "Authorization: Bearer sk_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "rates",
    "property_id": "1234567",
    "updates": [
      {
        "roomId": "123456701",
        "rateId": "98765",
        "dateRange": { "start": "2026-07-01", "end": "2026-07-07" },
        "price": 180,
        "currency": "USD",
        "restrictions": { "minStay": 2 }
      }
    ]
  }'

# Skip the read-back on a backfill you will reconcile separately
curl -X PUT https://api.repull.dev/v1/channels/booking/availability \
  -H "Authorization: Bearer sk_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"type": "rates", "verify": false, "property_id": "1234567", "updates": [{"roomId": "123456701", "rateId": "98765", "dateRange": {"start": "2027-01-05", "end": "2027-01-05"}, "price": 210, "currency": "USD", "occupancy": 4}]}'

Response

// 200 — the price was pushed and read back live
{
  "requested": 1,
  "occupancy": [
    { "roomId": "123456701", "rateId": "98765", "value": 4, "source": "request" }
  ],
  "applied": "verified",
  "verification": {
    "checked": 1,
    "matched": 1,
    "mismatched": 0,
    "dates": [
      { "date": "2026-11-04", "expectedPrice": 180, "bookingPrice": 180, "match": true }
    ]
  },
  "booking": { "ok": "" },
  "errors": []
}

// 200 — Booking.com acknowledged, but the price on the night did not change.
// Here the rate plan does not price at 6 people, so the amount was declined.
{
  "requested": 1,
  "occupancy": [
    { "roomId": "123456701", "rateId": "98765", "value": 6, "source": "request" }
  ],
  "applied": "mismatch",
  "verification": {
    "checked": 1,
    "matched": 0,
    "mismatched": 1,
    "dates": [
      { "date": "2026-11-04", "expectedPrice": 180, "bookingPrice": 0, "match": false }
    ]
  },
  "booking": { "ok": "" },
  "errors": []
}

// 200 — pushed, acknowledged, not checked. Not a failure; an unknown.
{
  "requested": 1,
  "occupancy": [
    { "roomId": "123456701", "rateId": "98765", "value": 4, "source": "rate_plan" }
  ],
  "applied": "unverified",
  "verification": { "checked": 0, "skipped": true, "reason": "verify=false" },
  "booking": { "ok": "" },
  "errors": []
}
AI