ChatBedsDevelopers
API reference

Reservations

Book stays, read and search them, change dates and guests, cancel under the hotel's policy, and add extras.

A reservation made through the API is a normal ChatBeds booking: it is priced by the hotel's pricing engine, shows on the hotel's tape chart, alerts the staff, and carries the source PARTNER:<partner> plus your own external_ref. It is booked as pay at the hotel; take money with a payment link or record a payment you took yourself.

The reservation object

Every operation on this page returns a reservation in this shape (search returns a list of them).

FieldTypeMeaning
iduuidStore it: every later call uses it
refstringThe short reference the hotel sees and the guest is told, such as A589DF
property_iduuid
statusstringconfirmed, checked_in, checked_out, cancelled or no_show. A booking made elsewhere at the hotel can also be pending; it holds its room like a confirmed one
sourcestringWho made it: PARTNER:<partner> for you; other values for the front desk, the booking page, other partners
external_refstring or nullYour reference, as you sent it
arrival, departuredateFirst night; day of departure
nights, adults, childreninteger
guestobjectfirst_name, last_name, email, phone
room_typeobject or null{"id", "name"}
unitobject or null{"id", "name"} once a room is assigned; null until the hotel assigns one
rate_planobject or null{"id", "name"}, or null for the room type's own rate
currencystring
totalnumberEverything charged on the folio (room, extras, fees, tax, charges)
paidnumberPayments received
balancenumbertotal minus paid. Negative means the hotel owes the guest a refund
cancellationobject or nullWhen cancelled: {"fee", "reason", "cancelled_at"}
created_at, updated_atdatetime

Create a reservation

POST/properties/{property_id}/reservations
Scope reservations:writeOperation reservation.create

Books a stay and returns it with 201 Created. Send the offer's total as expected_total, your own booking ID as external_ref, and an Idempotency-Key header.

Body

property_id uuid (path)required
The property.
room_type_id uuid
The room type to book, from the offer. Required unless you give unit_id.
unit_id uuid
A specific room. With room_type_id, it must be of that type. Without it, the hotel assigns a room later.
rate_plan_id uuid
The offer's rate_plan.id. Leave it out for the room type's own rate (rate_plan: null).
arrival daterequired
The first night, YYYY-MM-DD.
departure daterequired
The day the guest leaves.
adults integer
1 to 20. Default 1.
children integer
0 to 20. Default 0.
guest objectrequired
The lead guest. A new guest record is made for each booking; it is never matched to an existing guest by email.
guest.first_name stringrequired
1 to 100 characters.
guest.last_name string
Up to 100 characters. Default empty.
guest.email string
Up to 255 characters.
guest.phone string
Up to 50 characters. Include the country code, for example +14155550123.
extras array
Up to 20 items, each {"extra_id": uuid, "quantity": 1-99} (quantity defaults to 1). See extras.
external_ref string
Your reference for the booking. Up to 100 characters: letters, digits and . _ : - /. Unique per partner and property: a second booking with the same value is refused.
notes string
Up to 1,000 characters, shown to the hotel staff (arrival time, requests).
expected_total number
The total you showed the guest, 0 to 99,999,999.99. If the price is now different (by more than half a cent), nothing is booked and the answer is 409 with the new total. Strongly recommended.
Header
Idempotency-Key1 to 255 characters. Strongly recommended: use one per booking attempt, for example your booking ID, and send the same key on every retry. See Idempotency

Example

Request
curl -X POST "https://api.chatbeds.app/partner/v1/properties/19306340-c7cf-465a-93d3-0b7873a7e85d/reservations" \
  -H "Authorization: Bearer cbk_••••" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: b2f1c9e4-booking-BK-104233" \
  -d '{
    "room_type_id": "da3b4c87-c1ca-4f13-8c90-066900f16d48",
    "arrival": "2026-10-31",
    "departure": "2026-11-02",
    "adults": 2,
    "children": 0,
    "guest": {
      "first_name": "Daniel",
      "last_name": "Moore",
      "email": "daniel.moore@example.com",
      "phone": "+14155550123"
    },
    "external_ref": "BK-104233",
    "notes": "Late arrival, around 23:00",
    "expected_total": 180.0
  }'
201 Created
{
  "reservation": {
    "id": "a589df05-30ad-4ee5-9832-16ff6c2c1d0e",
    "ref": "A589DF",
    "property_id": "19306340-c7cf-465a-93d3-0b7873a7e85d",
    "status": "confirmed",
    "source": "PARTNER:sandbox",
    "external_ref": "BK-104233",
    "arrival": "2026-10-31",
    "departure": "2026-11-02",
    "nights": 2,
    "adults": 2,
    "children": 0,
    "guest": {
      "first_name": "Daniel",
      "last_name": "Moore",
      "email": "daniel.moore@example.com",
      "phone": "+14155550123"
    },
    "room_type": {
      "id": "da3b4c87-c1ca-4f13-8c90-066900f16d48",
      "name": "Standard"
    },
    "unit": null,
    "rate_plan": null,
    "currency": "USD",
    "total": 180.0,
    "paid": 0.0,
    "balance": 180.0,
    "cancellation": null,
    "created_at": "2026-10-10T05:09:47.271659+00:00",
    "updated_at": "2026-10-10T05:09:47+00:00"
  }
}

Sending the same request again with the same Idempotency-Key returns the same 201 body with the header Idempotent-Replayed: true, and books nothing.

Errors

StatusdetailWhat to do
409The price has changed: the total is now USD 180.00.Search offers again and show the guest the new price. Nothing was booked
409A booking with external_ref BK-104233 already exists (a589df05-30ad-4ee5-9832-16ff6c2c1d0e).This booking was already made: use the ID in the message, or reservation.search by external_ref
409No Standard room is available for the selected dates.Sold out since you searched. Search again
409Unit is already booked for the selected dates.The unit_id you chose is taken. Book by room type instead
409Standard is not on sale.The room type was switched off
409A request with this Idempotency-Key is already being processed.Two requests with the same key at once. Wait and retry with the same key
400Give room_type_id (and unit_id to choose the room).Neither was sent
400That unit is not of that room type.unit_id and room_type_id disagree
400external_ref: letters, digits and . _ : - / only, up to 100 characters.Fix the reference
400Standard is closed to new bookings on ..., Stays arriving on ... need at least ...The hotel's stay rules. Offers leave these out
400That rate plan belongs to another property.Wrong rate_plan_id
400Idempotency-Key must be 1 to 255 characters.
404Room type not found, Unit not found, Extra not found, Property not foundAn ID that is not this property's
422A list of field problemsA required field is missing or out of range, or the Idempotency-Key was used for a different request
422 Unprocessable Entity
{
  "detail": [
    {
      "loc": [
        "body",
        "departure"
      ],
      "msg": "Field required",
      "type": "missing"
    },
    {
      "loc": [
        "body",
        "guest"
      ],
      "msg": "Field required",
      "type": "missing"
    }
  ]
}

Get a reservation

GET/reservations/{reservation_id}
Scope reservations:readOperation reservation.get

Returns one reservation at the property, whoever made it. Use it to refresh your copy when a webhook arrives.

Parameters

reservation_id uuid (path)required
The reservation's id.

Example

Request
curl -X GET "https://api.chatbeds.app/partner/v1/reservations/a589df05-30ad-4ee5-9832-16ff6c2c1d0e" \
  -H "Authorization: Bearer cbk_••••"
200 OK
{
  "reservation": {
    "id": "a589df05-30ad-4ee5-9832-16ff6c2c1d0e",
    "ref": "A589DF",
    "property_id": "19306340-c7cf-465a-93d3-0b7873a7e85d",
    "status": "confirmed",
    "source": "PARTNER:sandbox",
    "external_ref": "BK-104233",
    "arrival": "2026-10-31",
    "departure": "2026-11-02",
    "nights": 2,
    "adults": 2,
    "children": 0,
    "guest": {
      "first_name": "Daniel",
      "last_name": "Moore",
      "email": "daniel.moore@example.com",
      "phone": "+14155550123"
    },
    "room_type": {
      "id": "da3b4c87-c1ca-4f13-8c90-066900f16d48",
      "name": "Standard"
    },
    "unit": null,
    "rate_plan": null,
    "currency": "USD",
    "total": 180.0,
    "paid": 0.0,
    "balance": 180.0,
    "cancellation": null,
    "created_at": "2026-10-10T05:09:47.271659+00:00",
    "updated_at": "2026-10-10T05:09:47+00:00"
  }
}

Errors

StatusdetailWhen
403The app token lacks reservations:read
404Reservation not foundNo such reservation at this property

Search reservations

GET/properties/{property_id}/reservations
Scope reservations:readOperation reservation.search

Finds reservations at the property by exact arrival date, exact departure date, guest last name or your external_ref. Give at least one of those four; status and limit only narrow the result. Results are sorted by arrival, then by when they were made.

Parameters

property_id uuid (path)required
The property.
arrival date (query)
Reservations arriving on exactly this date.
departure date (query)
Reservations leaving on exactly this date.
lastName string (query)
The guest's last name, matched in full and ignoring case. Up to 100 characters. last_name also works.
external_ref string (query)
Your reference, matched exactly. Up to 100 characters.
status string (query)
confirmed, checked_in, checked_out, cancelled or no_show.
limit integer (query)
1 to 100. Default 50.

Example

Request
curl -X GET "https://api.chatbeds.app/partner/v1/properties/19306340-c7cf-465a-93d3-0b7873a7e85d/reservations?external_ref=BK-104233" \
  -H "Authorization: Bearer cbk_••••"
200 OK
{
  "reservations": [
    {
      "id": "a589df05-30ad-4ee5-9832-16ff6c2c1d0e",
      "ref": "A589DF",
      "property_id": "19306340-c7cf-465a-93d3-0b7873a7e85d",
      "status": "confirmed",
      "source": "PARTNER:sandbox",
      "external_ref": "BK-104233",
      "arrival": "2026-10-31",
      "departure": "2026-11-02",
      "nights": 2,
      "adults": 2,
      "children": 0,
      "guest": {
        "first_name": "Daniel",
        "last_name": "Moore",
        "email": "daniel.moore@example.com",
        "phone": "+14155550123"
      },
      "room_type": {
        "id": "da3b4c87-c1ca-4f13-8c90-066900f16d48",
        "name": "Standard"
      },
      "unit": null,
      "rate_plan": null,
      "currency": "USD",
      "total": 180.0,
      "paid": 0.0,
      "balance": 180.0,
      "cancellation": null,
      "created_at": "2026-10-10T05:09:47.271659+00:00",
      "updated_at": "2026-10-10T05:09:47+00:00"
    }
  ]
}

No ranges, no pages

arrival and departure match one date, not a range, and there is no next page. To cover a period, search day by day; if a day returns limit results, narrow it with status. See Keep bookings in sync.

Errors

StatusdetailWhen
400Search by arrival, departure, last_name or external_ref.None of the four was given
400Unknown status. Use confirmed, checked_in, checked_out, cancelled or no_show.
403The app token lacks reservations:read
404Property not found
422A date that is not a date, or limit out of range

Modify a reservation

PATCH/reservations/{reservation_id}
Scope reservations:writeOperation reservation.modify

Changes the dates, the number of guests, the guest's details or the notes. Send only the fields that change. The room type and rate plan cannot change here: cancel and book again.

Body

reservation_id uuid (path)required
The reservation.
arrival date
New first night.
departure date
New day of departure.
adults integer
1 to 20.
children integer
0 to 20.
guest object
Any of first_name (1 to 100 characters), last_name (up to 100), email (up to 255), phone (up to 50). Fields you leave out are kept.
notes string
Up to 1,000 characters. Replaces the notes.

How the price follows a change:

ChangeEffect on the folio
Nights keptKeep the price they were booked at
New nightsPriced now, at today's rates
Nights droppedCome off the folio
Extras sold per nightFollow the new number of nights
Extras sold per personFollow the new number of guests
A booking with a price agreed by handKeeps its nightly rate for every night

There is no expected_total check on a change: read the new total in the response and show it to the guest. The room (or, for a booking without a room yet, the room type) must be free on the new nights, and the rate plan's minimum stay still applies.

Example

Request
curl -X PATCH "https://api.chatbeds.app/partner/v1/reservations/a589df05-30ad-4ee5-9832-16ff6c2c1d0e" \
  -H "Authorization: Bearer cbk_••••" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: BK-104233-change-1" \
  -d '{
    "adults": 2,
    "notes": "Late arrival, around 23:30; needs a cot"
  }'
200 OK
{
  "reservation": {
    "id": "a589df05-30ad-4ee5-9832-16ff6c2c1d0e",
    "ref": "A589DF",
    "property_id": "19306340-c7cf-465a-93d3-0b7873a7e85d",
    "status": "confirmed",
    "source": "PARTNER:sandbox",
    "external_ref": "BK-104233",
    "arrival": "2026-10-31",
    "departure": "2026-11-02",
    "nights": 2,
    "adults": 2,
    "children": 0,
    "guest": {
      "first_name": "Daniel",
      "last_name": "Moore",
      "email": "daniel.moore@example.com",
      "phone": "+14155550123"
    },
    "room_type": {
      "id": "da3b4c87-c1ca-4f13-8c90-066900f16d48",
      "name": "Standard"
    },
    "unit": null,
    "rate_plan": null,
    "currency": "USD",
    "total": 180.0,
    "paid": 0.0,
    "balance": 180.0,
    "cancellation": null,
    "created_at": "2026-10-10T05:09:47.271659+00:00",
    "updated_at": "2026-10-10T05:09:47+00:00"
  }
}

Notes are not part of the reservation object; the hotel sees them on the booking.

Errors

StatusdetailWhen
400Nothing to change.The body had no field to change
400Check-out date must be after check-in date.
400... needs a stay of at least ... nights. ...The new stay is shorter than the rate plan allows
409A reservation with status 'cancelled' can only have its guest details and notes changed.Dates or guests on a cancelled or checked-out booking
409The guest has already arrived, so the arrival date cannot change.The guest is checked in
409No ... room is available for the selected dates., Unit is already booked for the selected dates.The new nights are not free
403The app token lacks reservations:write
404Reservation not found

Cancel a reservation

POST/reservations/{reservation_id}/cancel
Scope reservations:writeOperation reservation.cancel

Cancels under the hotel's own cancellation policy. The fee the policy gives goes on the folio and the stay's charges come off; you cannot waive or change the fee. Payments already taken stay on the folio, so a negative balance is a refund the hotel owes the guest. The response includes the policy's explanation and the fee it charged.

Cancelling a reservation that is already cancelled changes nothing and answers with the reservation as it is, with policy: null. A no-show is also already cancelled.

Body

reservation_id uuid (path)required
The reservation.
reason string
Up to 255 characters, shown to the hotel. The body is optional.

Example

Request
curl -X POST "https://api.chatbeds.app/partner/v1/reservations/a589df05-30ad-4ee5-9832-16ff6c2c1d0e/cancel" \
  -H "Authorization: Bearer cbk_••••" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: BK-104233-cancel" \
  -d '{"reason": "Guest changed plans"}'

In this recorded run, a USD 100 payment had been recorded before cancelling. The sandbox hotel has no cancellation policy, so the fee is 0, the charges come off, and the USD 100 remains as a refund due (balance: -100.0).

200 OK
{
  "reservation": {
    "id": "a589df05-30ad-4ee5-9832-16ff6c2c1d0e",
    "ref": "A589DF",
    "property_id": "19306340-c7cf-465a-93d3-0b7873a7e85d",
    "status": "cancelled",
    "source": "PARTNER:sandbox",
    "external_ref": "BK-104233",
    "arrival": "2026-10-31",
    "departure": "2026-11-02",
    "nights": 2,
    "adults": 2,
    "children": 0,
    "guest": {
      "first_name": "Daniel",
      "last_name": "Moore",
      "email": "daniel.moore@example.com",
      "phone": "+14155550123"
    },
    "room_type": {
      "id": "da3b4c87-c1ca-4f13-8c90-066900f16d48",
      "name": "Standard"
    },
    "unit": null,
    "rate_plan": null,
    "currency": "USD",
    "total": 0.0,
    "paid": 100.0,
    "balance": -100.0,
    "cancellation": {
      "fee": 0.0,
      "reason": "Guest changed plans",
      "cancelled_at": "2026-10-10T05:09:47.509902+00:00"
    },
    "created_at": "2026-10-10T05:09:47.271659+00:00",
    "updated_at": "2026-10-10T05:09:47+00:00"
  },
  "policy": {
    "explanation": "This hotel has no cancellation policy, so nothing is charged.",
    "fee": 0.0
  }
}

Errors

StatusdetailWhen
409The guest is checked in. Check them out instead of cancelling.
409This stay is already finished and cannot be cancelled.The guest has checked out
403The app token lacks reservations:write
404Reservation not found

Add an extra

POST/reservations/{reservation_id}/extras
Scope reservations:writeOperation reservation.addExtra

Adds an extra (breakfast, airport pick-up) to a confirmed or checked-in booking. It is priced for the booking's nights and guests by the extra's unit (per stay, per night, per person, per person per night), times quantity, and taxed like extras chosen at booking. It goes on the folio as its own line and the response is the updated reservation, with the new total and balance.

Body

reservation_id uuid (path)required
The reservation.
extra_id uuidrequired
quantity integer
1 to 99. Default 1.

Example

Request
curl -X POST "https://api.chatbeds.app/partner/v1/reservations/a589df05-30ad-4ee5-9832-16ff6c2c1d0e/extras" \
  -H "Authorization: Bearer cbk_••••" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: BK-104233-extra-breakfast" \
  -d '{"extra_id": "<extra id from extra.list>", "quantity": 1}'

The sandbox hotel has no extras, so there is no recorded response. The answer is 200 OK with {"reservation": {...}}, the same object as Get a reservation, its total and balance raised by the extra's amount (and tax). To see the extra's own line, read the folio.

Errors

StatusdetailWhen
409Extras cannot be added to a booking that is cancelled. (or checked out, no show)Only confirmed and checked-in bookings take extras
400... is not on offer.The hotel has switched the extra off
403The app token lacks reservations:write
404Extra not foundNot an extra of this property
404Reservation not found
422extra_id missing or not a UUID, quantity out of range

Building something?

On this page