> ## Documentation Index
> Fetch the complete documentation index at: https://docs.d-edge.com/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> This site documents the D-EDGE APIs for technology partners (web agencies, OTAs, PMS and RMS vendors, booking and CRM tools). It is written for developers integrating with hotels that use the D-EDGE platform.
> Seven APIs, grouped by domain. Connectivity: Channel Manager API (distribute a hotel's inventory to your channel and send bookings back). Pricing & Availability: Best Price API (best offers to highlight), Quotation API (all bookable offers for a stay), Daily Rates API (daily availability between two dates). Booking: Booking Engine API (a hotel's full direct booking funnel), Gift Shop API (gift vouchers from catalogue to payment). Guest Management: CRM API (guest profiles).
> Pick the API by the need: to display prices, use the Best Price API or the Daily Rates API; to quote a specific stay, use the Quotation API; to book, use the Booking Engine API; to sell gift vouchers, use the Gift Shop API; to manage guest profiles, use the CRM API; to receive hotel inventory and send bookings back as a distribution channel, use the Channel Manager API.
> Base URLs, hotel identifiers, and credentials are delivered by the D-EDGE partnership team during onboarding. Do not invent base URLs, endpoints, parameters, or example credentials that do not appear on these pages.
> Authentication differs per API: OAuth 1.0 for Best Price, Quotation, Daily Rates, and Booking Engine; an X-API-KEY header for Gift Shop; OAuth 2.0 client credentials for CRM; partner-defined credentials carried in the XML message for the Channel Manager API. Read each API's Authentication page before writing code.
> A mock environment returns realistic but fictitious data without credentials. The Postman and Insomnia collections on the API collections page target it by default. Use it for exploration and tests, never for production traffic.
> Use the official names exactly: D-EDGE, D-EDGE platform, Channel Manager API, partnership team. Do not use Back Office or Extranet.
> Each API has a Changelog page. Check it for the current behaviour before relying on an older answer. For questions these pages do not answer, direct the reader to the Contact us page.

# Best rate per room type

> Show the cheapest offer for each room on a listing page

A "from" price per room helps guests compare options at a glance, before they commit to a date. The Best Price Rooms endpoint returns per-room pricing across your date window in a single call.

## Prerequisites

Before building a per-room listing, make sure you have:

* A working Best Price call. If not, follow the [Quick start](/best-price-api/get-started/quick-start.md) first.
* A hotel ID and a group ID.
* A target date window (typically 30 to 90 days).

## How it works

The Rooms endpoint returns one entry per available room and requested strategy, with the best price found over your date window and the arrival date it applies to. With a single call and a single strategy in `behaviours` (`LowestLengthOfStay` when you send none), you get one "from" price per room, with no aggregation on your side.

Rooms that are not bookable on any day in the window are absent from the response.

## Build the listing

> [!NOTE]
>
> The examples below assume the OAuth signing setup from the [Quick start](/best-price-api/get-started/quick-start.md).

### 1. Call Best Price Rooms once

Send one request to `/BestPrice/Rooms` with your date range and party. The response is an array with one entry per room.

```bash cURL theme={null}
curl --request POST \
  --url https://{apiBaseUrl}/Planning/2018A/BestPrice/Rooms \
  --header 'Authorization: OAuth ...' \
  --header 'Content-Type: application/json' \
  --data '{
    "beginDate": "2026-12-07",
    "endDate": "2027-01-05",
    "guests": {"adults": 2},
    "filter": {
      "ratePlan": {"hotelId": <hotelId>, "groupId": <groupId>},
      "currency": "EUR"
    }
  }'
```

```javascript Node.js theme={null}
const url = "https://{apiBaseUrl}/Planning/2018A/BestPrice/Rooms";

const response = await fetch(url, {
  method: "POST",
  headers: { ...authHeaders, "Content-Type": "application/json" },
  body: JSON.stringify({
    beginDate: "2026-12-07",
    endDate: "2027-01-05",
    guests: { adults: 2 },
    filter: {
      ratePlan: { hotelId: <hotelId>, groupId: <groupId> },
      currency: "EUR",
    },
  }),
});
const data = await response.json();
```

```python Python theme={null}
response = session.post(
    "https://{apiBaseUrl}/Planning/2018A/BestPrice/Rooms",
    json={
        "beginDate": "2026-12-07",
        "endDate": "2027-01-05",
        "guests": {"adults": 2},
        "filter": {
            "ratePlan": {"hotelId": <hotelId>, "groupId": <groupId>},
            "currency": "EUR",
        },
    },
)
data = response.json()
```

```php PHP theme={null}
$response = $client->post('Planning/2018A/BestPrice/Rooms', [
    'json' => [
        'beginDate' => '2026-12-07',
        'endDate'   => '2027-01-05',
        'guests'    => ['adults' => 2],
        'filter'    => [
            'ratePlan' => ['hotelId' => <hotelId>, 'groupId' => <groupId>],
            'currency' => 'EUR',
        ],
    ],
]);
$data = json_decode($response->getBody(), true);
```

```csharp C# theme={null}
var request = new RestRequest("/BestPrice/Rooms", Method.Post);
request.AddJsonBody(new
{
    beginDate = "2026-12-07",
    endDate = "2027-01-05",
    guests = new { adults = 2 },
    filter = new
    {
        ratePlan = new { hotelId = <hotelId>, groupId = <groupId> },
        currency = "EUR"
    }
});

var response = await client.ExecuteAsync(request);
var data = JsonDocument.Parse(response.Content!).RootElement;
```

```java Java theme={null}
String body = mapper.writeValueAsString(Map.of(
    "beginDate", "2026-12-07",
    "endDate", "2027-01-05",
    "guests", Map.of("adults", 2),
    "filter", Map.of(
        "ratePlan", Map.of("hotelId", <hotelId>, "groupId", <groupId>),
        "currency", "EUR"
    )
));

HttpPost request = new HttpPost("https://{apiBaseUrl}/Planning/2018A/BestPrice/Rooms");
request.setEntity(new StringEntity(body, "UTF-8"));
request.setHeader("Content-Type", "application/json");
consumer.sign(request);

JsonNode data;
try (CloseableHttpResponse response = client.execute(request)) {
    data = mapper.readTree(EntityUtils.toString(response.getEntity()));
}
```

### 2. Index the response by room

With a single strategy in `behaviours`, each room appears once, with its best `totalPrice` over the window and the `arrivalDate` it applies to. Key the entries by `roomId` to look up each room's "from" price and currency.

```javascript Node.js theme={null}
function indexByRoom(data) {
  const byRoom = new Map();
  for (const entry of data) {
    byRoom.set(entry.roomId, entry);
  }
  return byRoom;
}

const byRoom = indexByRoom(data);
```

```python Python theme={null}
def index_by_room(data):
    by_room = {}
    for entry in data:
        by_room[entry["roomId"]] = entry
    return by_room

by_room = index_by_room(data)
```

```php PHP theme={null}
function indexByRoom(array $data): array {
    $byRoom = [];
    foreach ($data as $entry) {
        $byRoom[$entry['roomId']] = $entry;
    }
    return $byRoom;
}

$byRoom = indexByRoom($data);
```

```csharp C# theme={null}
var byRoom = data.EnumerateArray()
    .ToDictionary(
        d => d.GetProperty("roomId").GetInt32(),
        d => d
    );
```

```java Java theme={null}
Map<Integer, JsonNode> byRoom = new HashMap<>();
for (JsonNode entry : data) {
    int roomId = entry.get("roomId").asInt();
    byRoom.put(roomId, entry);
}
```

### 3. Render the room cards

Display each room with its "from" price. For rooms with no entry in the response, show a soft fallback rather than a hard "Sold out", since availability changes throughout the day.

```javascript Node.js theme={null}
rooms.forEach(room => {
  const cheapest = byRoom.get(room.id);
  renderRoomCard({
    roomId: room.id,
    name: room.name,
    from: cheapest
      ? { price: cheapest.totalPrice, currency: cheapest.currency }
      : { fallback: "Check availability" },
  });
});
```

```python Python theme={null}
for room in rooms:
    cheapest = by_room.get(room["id"])
    render_room_card({
        "roomId": room["id"],
        "name": room["name"],
        "from": (
            {"price": cheapest["totalPrice"], "currency": cheapest["currency"]}
            if cheapest else {"fallback": "Check availability"}
        ),
    })
```

```php PHP theme={null}
foreach ($rooms as $room) {
    $cheapest = $byRoom[$room['id']] ?? null;
    renderRoomCard([
        'roomId' => $room['id'],
        'name'   => $room['name'],
        'from'   => $cheapest
            ? ['price' => $cheapest['totalPrice'], 'currency' => $cheapest['currency']]
            : ['fallback' => 'Check availability'],
    ]);
}
```

```csharp C# theme={null}
foreach (var room in rooms)
{
    var cheapest = byRoom.TryGetValue(room.Id, out var c) ? (JsonElement?)c : null;
    RenderRoomCard(new
    {
        roomId = room.Id,
        name = room.Name,
        from = cheapest.HasValue
            ? (object)new
            {
                price = cheapest.Value.GetProperty("totalPrice").GetDecimal(),
                currency = cheapest.Value.GetProperty("currency").GetString()
            }
            : new { fallback = "Check availability" }
    });
}
```

```java Java theme={null}
for (Room room : rooms) {
    JsonNode cheapest = byRoom.get(room.id());
    Object from = cheapest != null
        ? Map.of(
            "price", cheapest.get("totalPrice").decimalValue(),
            "currency", cheapest.get("currency").asText()
        )
        : Map.of("fallback", "Check availability");
    renderRoomCard(Map.of(
        "roomId", room.id(),
        "name", room.name(),
        "from", from
    ));
}
```

## Tips

* **Cache aggressively**. One call per (date range, party) combination, easy cache key. Listings load instantly from cache between API refreshes.
* **Use a tight date window**. 30 days is usually enough for listing display. A 90-day window costs more per call without changing the "from" price most of the time.
* **Handle rooms missing from the response**. The endpoint returns entries only for rooms bookable on at least one arrival date in the window. A room that never appears might be fully sold across the period. Show a soft fallback rather than hiding the room from the listing.

## Related

> **[Reference](/best-price-api/build/reference/rooms.md)**
>
> Full schema for the Rooms endpoint.

> **[Best practices](/best-price-api/build/best-practices.md)**
>
> Caching, performance, and resilience patterns.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.