Docs/Channels/Booking.com

Properties & listings on Booking.com

A Booking.com property is a building. Its rooms are what guests book, and each room maps to one Repull listing. Getting that shape right is what makes every other Booking.com endpoint make sense — including which of the two id spaces each one takes.

The model

When a host connects Booking.com they claim a property by its hotel id. We import its rooms. The last step of the connect flow is room mapping: the host says which Repull listing each room corresponds to.

Booking.com property  "hotel_id": 5432505      ← the building
└── room             "roomBookingId": 543250501   ← what a guest books
    └── Repull listing  "listingId": 28028        ← what you address in the API

A one-room villa gives you the simple case above. A twenty-unit aparthotel is a single property holding twenty rooms mapped to twenty listings — that is normal, not an edge case. The reverse happens too: the same unit can be published under more than one Booking.com property, usually because it was re-listed over time.

  • One property → many listings, one per mapped room.
  • One listing → possibly several properties, if it is published under more than one.
  • A room that is not mapped yet belongs to no listing, and its reservations have nowhere to land.

Which id each endpoint takes

This is the one thing worth reading twice. Two endpoints with properties in the path take a Repull listing id, not a Booking.com hotel id. Passing the wrong one gets you a 404 that looks like a permissions problem.

EndpointId it takes
GET /v1/channels/booking/propertiesnone — lists everything
GET /v1/channels/booking/properties/{id}Repull listing id
GET /v1/channels/booking/properties/{id}/roomsRepull listing id
GET/PUT /v1/channels/booking/listings/{id}/pricingRepull listing id
PUT /v1/channels/booking/availabilityBooking.com hotel id (property_id)
GET/POST /v1/channels/booking/contentBooking.com hotel id (property_id)

The rule of thumb

Anything with an id in the path takes a Repull listing id. Anything that takes property_id as a query or body field takes a Booking.com hotel id. The naming is historical; changing it would break every integration already built on it, so the error messages name the id space instead.

Reading the map

One call gives you the whole picture — every property, and the listings under each.

curl https://api.repull.dev/v1/channels/booking/properties \
  -H "Authorization: Bearer sk_live_YOUR_KEY"
[
  {
    "connectionId": "775",
    "hotelId": "5432505",
    "active": true,
    "syncEnabled": true,
    "mappingStatus": "mapped",
    "listings": [
      {
        "listingId": "28028",
        "name": "Villa MarSalada",
        "city": "La Frontera",
        "roomBookingId": "543250501",
        "roomName": "Room MarSalada",
        "mappedVia": "room"
      }
    ]
  },
  {
    "connectionId": "776",
    "hotelId": "5432506",
    "active": true,
    "mappingStatus": "unmapped",
    "listings": []
  }
]

Each property appears exactly once. listings[].listingId is what you pass to the listing-addressed endpoints above; hotelId is what you pass as property_id to the hotel-addressed ones; listings[].roomBookingId is the roomId an availability or rate write takes.

When a property shows no rooms

A property with "mappingStatus": "unmapped" and an empty listings array is connected but not finished. The host claimed the hotel and we imported its rooms, but nobody has said which listing each room is. Until they do:

  • the listing-addressed endpoints have no listing id to accept, so they answer 404 not_found;
  • reservations arriving for those rooms have no listing to attach to.

The fix is to finish room mapping. Read the rooms awaiting a decision, then submit the choices:

# Rooms imported for the connect session, with their mapping state
curl "https://api.repull.dev/v1/connect/booking/rooms?sessionId=cs_..." \
  -H "Authorization: Bearer sk_live_YOUR_KEY"

# Map each room to a listing (or ask us to create one)
curl -X POST https://api.repull.dev/v1/connect/booking/map-rooms \
  -H "Authorization: Bearer sk_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "sessionId": "cs_...",
    "mappings": [
      { "roomId": 1333, "listingId": 28028 },
      { "roomId": 1334, "create": true }
    ]
  }'

Hosts going through the hosted connect page do this themselves on the last screen — see Connect Booking.com. Re-check GET /v1/channels/booking/properties afterwards: the property should read mapped, with its listings attached.

An unmapped property is still listed

It would be tidier to hide a property with nothing mapped under it. We do not, deliberately: a hidden property is indistinguishable from one that was never connected, which leaves you debugging the wrong thing. mappingStatus tells you which of the two you have.

When one listing is under several properties

Uncommon, but real. When it happens, a listing-addressed endpoint has to decide which property you meant:

  • Reads use the oldest mapping and hand you the rest in otherHotelIds, so you can tell it happened.
  • Writes refuse with 409 ambiguous_booking_mapping and push nothing. Guessing which property gets your rates is not a mistake you would find quickly.

Either way, ?hotel_id= settles it:

curl -X PUT "https://api.repull.dev/v1/channels/booking/listings/6001/pricing?hotel_id=8000002" \
  -H "Authorization: Bearer sk_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "updates": [
      {
        "roomId": "800000201",
        "rateId": "1234567",
        "dateRange": { "start": "2026-10-01", "end": "2026-10-07" },
        "price": 180,
        "currency": "EUR"
      }
    ]
  }'

roomId and rateId come from GET /v1/channels/booking/properties/{id}/rooms, which returns each room with every rate plan under it.

Troubleshooting

What you seeWhat it means
Empty array from /propertiesNo Booking.com property is connected to this workspace at all. Start with Connect Booking.com.
mappingStatus: "unmapped"Connected, rooms imported, mapping unfinished. Submit POST /v1/connect/booking/map-rooms.
404 not_found on a listing-addressed pathEither you passed a Booking.com hotel id where a Repull listing id belongs, or that listing has no mapped room. The message says which.
403 listing_inactiveThe listing is mapped but deactivated. It keeps syncing; activate it with PATCH /v1/listings/{id}.
409 ambiguous_booking_mappingThe listing is published under several properties. Add ?hotel_id=; the error lists the valid ids.
A listing missing from listings[]Inactive listings are left out of collections. Find them with GET /v1/listings?status=inactive.

Related: Manage Properties, Update Pricing, Push Availability, Identifiers.

AI