> ## 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.

# Quick start

> Make your first call

This guide walks you through your first call to the Quotation API. You will set up OAuth 1.0 signing, send a request to the **Stay quotation** endpoint, and inspect the response.

> [!NOTE]
>
> **No credentials yet?** Import the [API collections](/overview/resources/api-collections.md) and run any request against the mock environment straight away, with no credentials. Add your OAuth 1.0 credentials when you are ready to call the live API.

## Prerequisites

Get the following from D-EDGE before starting:

* **OAuth 1.0 credentials**: consumer key, consumer secret, token key, and token secret.
* **API base URL**: the base URL for your environment.
* **Hotel ID and Group ID**: the hotel you want to query.

All are delivered during the build step of your [integration journey](/overview/get-started/your-integration-journey.md), after the partnership agreement.

## 1. Install an OAuth 1.0 library

Use a battle-tested library to handle the signing. Skip this step if you only use cURL.

```bash Node.js theme={null}
npm install oauth-1.0a
```

```bash Python theme={null}
pip install requests-oauthlib
```

```bash PHP theme={null}
composer require guzzlehttp/oauth-subscriber
```

```bash C# theme={null}
dotnet add package RestSharp
```

```xml Java theme={null}
<dependency>
    <groupId>oauth.signpost</groupId>
    <artifactId>signpost-commonshttp4</artifactId>
    <version>2.1.1</version>
</dependency>
```

## 2. Make your first call

Send a `POST` to the **Stay quotation** endpoint with a minimal request body. The exact field requirements are documented in the [Reference](/quotation-api/build/reference/stay-quotation.md).

```bash cURL theme={null}
curl --request POST \
  --url https://{apiBaseUrl}/Planning/2018A/Quotation/GetStayPlanning \
  --header 'Authorization: OAuth oauth_consumer_key="YOUR_CONSUMER_KEY",
    oauth_token="HOTEL_TOKEN_KEY",
    oauth_signature_method="HMAC-SHA1",
    oauth_timestamp="1714128000",
    oauth_nonce="abc123",
    oauth_version="1.0",
    oauth_signature="..."' \
  --header 'Content-Type: application/json' \
  --data '{
    "arrivalDate": "YYYY-MM-DD",
    "nightCount": 2,
    "guests": [{"adults": 2}],
    "filter": {
      "ratePlans": [{"groupId": <groupId>, "hotels": {"exceptions": [<hotelId>], "default": "Excluded"}}]
    },
    "layout": {
      "levels": [{
        "name": "ArticleRate",
        "properties": ["Status", "Availability", "TotalPrice", "IncludedArticles", "Occupancies"]
      }]
    }
  }'
```

```javascript Node.js theme={null}
import OAuth from "oauth-1.0a";
import crypto from "crypto";

const oauth = OAuth({
  consumer: {
    key: process.env.DEDGE_CONSUMER_KEY,
    secret: process.env.DEDGE_CONSUMER_SECRET,
  },
  signature_method: "HMAC-SHA1",
  hash_function(base_string, key) {
    return crypto.createHmac("sha1", key).update(base_string).digest("base64");
  },
});

const token = {
  key: process.env.DEDGE_TOKEN_KEY,
  secret: process.env.DEDGE_TOKEN_SECRET,
};

const url = "https://{apiBaseUrl}/Planning/2018A/Quotation/GetStayPlanning";
const body = {
  arrivalDate: "YYYY-MM-DD",
  nightCount: 2,
  guests: [{ adults: 2 }],
  filter: {
    ratePlans: [
      { groupId: <groupId>, hotels: { exceptions: [<hotelId>], default: "Excluded" } },
    ],
  },
  layout: {
    levels: [
      {
        name: "ArticleRate",
        properties: ["Status", "Availability", "TotalPrice", "IncludedArticles", "Occupancies"],
      },
    ],
  },
};

const response = await fetch(url, {
  method: "POST",
  headers: {
    ...oauth.toHeader(oauth.authorize({ url, method: "POST" }, token)),
    "Content-Type": "application/json",
  },
  body: JSON.stringify(body),
});

console.log(response.status, await response.json());
```

```python Python theme={null}
import os
from requests_oauthlib import OAuth1Session

session = OAuth1Session(
    client_key=os.environ["DEDGE_CONSUMER_KEY"],
    client_secret=os.environ["DEDGE_CONSUMER_SECRET"],
    resource_owner_key=os.environ["DEDGE_TOKEN_KEY"],
    resource_owner_secret=os.environ["DEDGE_TOKEN_SECRET"],
)

response = session.post(
    "https://{apiBaseUrl}/Planning/2018A/Quotation/GetStayPlanning",
    json={
        "arrivalDate": "YYYY-MM-DD",
        "nightCount": 2,
        "guests": [{"adults": 2}],
        "filter": {
            "ratePlans": [
                {
                    "groupId": <groupId>,
                    "hotels": {"exceptions": [<hotelId>], "default": "Excluded"},
                }
            ],
        },
        "layout": {
            "levels": [
                {
                    "name": "ArticleRate",
                    "properties": ["Status", "Availability", "TotalPrice", "IncludedArticles", "Occupancies"],
                }
            ]
        },
    },
)

print(response.status_code)
print(response.json())
```

```php PHP theme={null}
require 'vendor/autoload.php';

use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Subscriber\Oauth\Oauth1;

$stack = HandlerStack::create();

$middleware = new Oauth1([
    'consumer_key'    => getenv('DEDGE_CONSUMER_KEY'),
    'consumer_secret' => getenv('DEDGE_CONSUMER_SECRET'),
    'token'           => getenv('DEDGE_TOKEN_KEY'),
    'token_secret'    => getenv('DEDGE_TOKEN_SECRET'),
]);

$stack->push($middleware);

$client = new Client([
    'base_uri' => 'https://{apiBaseUrl}/',
    'handler'  => $stack,
    'auth'     => 'oauth',
]);

$response = $client->post('Planning/2018A/Quotation/GetStayPlanning', [
    'json' => [
        'arrivalDate' => 'YYYY-MM-DD',
        'nightCount'  => 2,
        'guests'      => [['adults' => 2]],
        'filter'      => [
            'ratePlans' => [[
                'groupId' => <groupId>,
                'hotels'  => ['exceptions' => [<hotelId>], 'default' => 'Excluded'],
            ]],
        ],
        'layout' => [
            'levels' => [[
                'name'       => 'ArticleRate',
                'properties' => ['Status', 'Availability', 'TotalPrice', 'IncludedArticles', 'Occupancies'],
            ]],
        ],
    ],
]);

echo $response->getStatusCode() . "\n";
echo $response->getBody();
```

```csharp C# theme={null}
using RestSharp;
using RestSharp.Authenticators.OAuth;

var options = new RestClientOptions("https://{apiBaseUrl}/Planning/2018A")
{
    Authenticator = OAuth1Authenticator.ForProtectedResource(
        consumerKey: Environment.GetEnvironmentVariable("DEDGE_CONSUMER_KEY"),
        consumerSecret: Environment.GetEnvironmentVariable("DEDGE_CONSUMER_SECRET"),
        token: Environment.GetEnvironmentVariable("DEDGE_TOKEN_KEY"),
        tokenSecret: Environment.GetEnvironmentVariable("DEDGE_TOKEN_SECRET"),
        signatureMethod: OAuthSignatureMethod.HmacSha1)
};
var client = new RestClient(options);

var request = new RestRequest("/Quotation/GetStayPlanning", Method.Post);
request.AddJsonBody(new
{
    arrivalDate = "YYYY-MM-DD",
    nightCount = 2,
    guests = new[] { new { adults = 2 } },
    filter = new
    {
        ratePlans = new[]
        {
            new
            {
                groupId = <groupId>,
                hotels = new { exceptions = new[] { <hotelId> }, @default = "Excluded" }
            }
        }
    },
    layout = new
    {
        levels = new[]
        {
            new
            {
                name = "ArticleRate",
                properties = new[] { "Status", "Availability", "TotalPrice", "IncludedArticles", "Occupancies" }
            }
        }
    }
});

var response = await client.ExecuteAsync(request);
Console.WriteLine(response.StatusCode);
Console.WriteLine(response.Content);
```

```java Java theme={null}
import com.fasterxml.jackson.databind.ObjectMapper;
import oauth.signpost.OAuthConsumer;
import oauth.signpost.commonshttp.CommonsHttpOAuthConsumer;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;

import java.util.List;
import java.util.Map;

OAuthConsumer consumer = new CommonsHttpOAuthConsumer(
    System.getenv("DEDGE_CONSUMER_KEY"),
    System.getenv("DEDGE_CONSUMER_SECRET")
);
consumer.setTokenWithSecret(
    System.getenv("DEDGE_TOKEN_KEY"),
    System.getenv("DEDGE_TOKEN_SECRET")
);

ObjectMapper mapper = new ObjectMapper();
String body = mapper.writeValueAsString(Map.of(
    "arrivalDate", "YYYY-MM-DD",
    "nightCount", 2,
    "guests", List.of(Map.of("adults", 2)),
    "filter", Map.of(
        "ratePlans", List.of(Map.of(
            "groupId", <groupId>,
            "hotels", Map.of(
                "exceptions", List.of(<hotelId>),
                "default", "Excluded"
            )
        ))
    ),
    "layout", Map.of(
        "levels", List.of(Map.of(
            "name", "ArticleRate",
            "properties", List.of("Status", "Availability", "TotalPrice", "IncludedArticles", "Occupancies")
        ))
    )
));

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

try (CloseableHttpClient client = HttpClients.createDefault()) {
    client.execute(request);
}
```

## 3. Inspect the response

A successful response returns `200 OK` with a JSON object grouped by rate plan, then by hotel, then by entity. Each entity is one room and rate combination, with availability and pricing for the requested stay.

```json theme={null}
{
  "defaultCurrency": "EUR",
  "ratePlans": [
    {
      "groupId": 12,
      "hotels": [
        {
          "hotelId": 6789,
          "entities": [
            {
              "level": "ArticleRate",
              "roomId": 67890,
              "rateId": 12345,
              "currency": "EUR",
              "status": "Available",
              "availability": 4,
              "totalPrice": 220,
              "guests": {"adults": 2}
            },
            {
              "level": "ArticleRate",
              "roomId": 67891,
              "rateId": 12346,
              "currency": "EUR",
              "status": "Available",
              "availability": 2,
              "totalPrice": 280,
              "guests": {"adults": 2}
            }
          ]
        }
      ]
    }
  ]
}
```

See the [response schema](/quotation-api/build/reference/stay-quotation.md) for the full structure.

## Common issues

| Status | Likely cause | Where to look |
| - | - | - |
| `401` | Signing issue: invalid credentials, clock drift, or reused nonce | [Authentication](/quotation-api/build/guidelines/authentication.md) |
| `400` | Validation error: malformed body or missing field | [Responses](/quotation-api/build/guidelines/responses.md) |
| `403` | Token does not grant access to this hotel | [Contact us](/overview/resources/contact-us.md) |

## Next steps

> **[Reference](/quotation-api/build/reference/stay-quotation.md)**
>
> Endpoint specifications, parameters, and response schemas.

> **[Use cases](/quotation-api/resources/use-cases/bookable-offers-showcase.md)**
>
> Showcase every bookable offer for a chosen stay.

> **[Best practices](/quotation-api/build/best-practices.md)**
>
> Patterns to build responsibly and run reliably at scale.


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