
# Test More Scenarios

## Status: not yet available

> **The `Test` header is accepted but no scenario is honoured yet.** Every Trade
> API route parses the header and carries it on the request context, and nothing
> downstream reads it. A call sent with `Test: scenario=soldOut` is served as an
> ordinary live search against your enabled suppliers — the same response you
> would get with no `Test` header at all.
>
> **Do not treat a scenario run as evidence that your unhappy-path handling
> works.** A `soldOut` or `serviceUnavailable` request that comes back with a
> normal populated result set has not exercised your error path; it has told you
> nothing. Until this page loses its status notice, cover those paths with your
> own fixtures or a stubbed transport, not with this header.

This page documents the vocabulary the header will use, so an integration
written against it does not have to change when the switches land.

## Test Header Format

Values are supplied as URL query-string key/value pairs:

```http
Test: key1=value1&key2=value2&key3=value3
```

### Basic Syntax

```http
Test: scenario=priceChanged&hotel=HC1
```

### Multiple Parameters

```http
Test: scenario=soldOut&hotel=HC1&supplier=dida&rawcache=off
```

Sending an unrecognised key or value is safe: the server ignores what it does
not understand and the call proceeds exactly as if no `Test` header had been
sent. Today that describes every key on this page.

## Reserved Scenarios

| Value                           | Intended effect                                                  | What it will let you prove                                       |
| ------------------------------- | ---------------------------------------------------------------- | ---------------------------------------------------------------- |
| `scenario=available`            | The ordinary availability path                                   | Your client reads and renders a successful search correctly      |
| `scenario=soldOut`              | A hotel or room comes back with no inventory                     | Your app degrades cleanly when nothing is bookable               |
| `scenario=priceChanged`         | The price moves between the search response and the booking call | Your app surfaces a price difference rather than booking blindly |
| `scenario=serviceUnavailable`   | A supplier is offline for the duration of the call               | Your app returns an error a human can act on                     |
| `scenario=unknownInternalError` | An unanticipated system failure                                  | Your catch-all error handling holds                              |

### Cache Control Parameters

`rawcache` governs how supplier responses are cached for the request:

- `rawcache=on` (default): caching enabled
- `rawcache=off`: caching disabled — always retrieve fresh data
- `rawcache=bypass`: skip the cache for this request only
- `rawcache=only`: serve from cache only; do not call the supplier

`rawttl` sets how long the cached entry lives:

```http
Test: scenario=available&rawttl=300s
Test: scenario=available&rawttl=1h
Test: scenario=available&rawttl=2d
```

### Scoping Parameters

`hotel` points a scenario at one property, `supplier` at one supplier
connection:

```http
Test: scenario=soldOut&hotel=HC1
Test: scenario=serviceUnavailable&supplier=dida
Test: scenario=priceChanged&supplier=derbysoft
```

## Request Bodies

The bodies below are ordinary, valid requests — they are what the endpoints
accept today, with or without the header. Search takes `roomOccupancies`, one
entry per room, each carrying `adultCount` and optional `childrenAges`. There is
no `occupancy` field; sending one fails validation with
`400 {"code":100000400}`.

### Example 1: HotelRates

```http
POST /api/search/hotelRates
Authorization: Bearer your-jwt-token
Session-Id: 374337a797454a344ad999c7730da01c
Test: scenario=priceChanged&hotel=HC1
Content-Type: application/json

{
  "hotelId": "HC1",
  "checkIn": "2026-02-15",
  "checkOut": "2026-02-17",
  "roomOccupancies": [{ "adultCount": 2, "childrenAges": [] }]
}
```

### Example 2: HotelList

```http
POST /api/search/hotelList
Authorization: Bearer your-jwt-token
Session-Id: 374337a797454a344ad999c7730da01c
Test: scenario=soldOut&supplier=dida&rawcache=off
Content-Type: application/json

{
  "destinationId": "804028047",
  "checkIn": "2026-02-15",
  "checkOut": "2026-02-17",
  "roomOccupancies": [{ "adultCount": 2, "childrenAges": [] }]
}
```

### Example 3: HotelRates against an unavailable supplier

```http
POST /api/search/hotelRates
Authorization: Bearer your-jwt-token
Session-Id: 374337a797454a344ad999c7730da01c
Test: scenario=serviceUnavailable&supplier=derbysoft&rawttl=0s
Content-Type: application/json

{
  "hotelId": "HC1",
  "checkIn": "2026-02-15",
  "checkOut": "2026-02-17",
  "roomOccupancies": [{ "adultCount": 2, "childrenAges": [] }]
}
```

## JavaScript/Node.js Example

```javascript
async function testScenario(params = {}) {
  const testHeader = Object.entries(params)
    .map(([key, value]) => `${key}=${value}`)
    .join("&");

  const response = await fetch("/api/search/hotelList", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${token}`,
      "Session-Id": sessionId,
      Test: testHeader,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      destinationId: "804028047",
      checkIn: "2026-02-15",
      checkOut: "2026-02-17",
      roomOccupancies: [{ adultCount: 2, childrenAges: [] }],
    }),
  });

  return response.json();
}

// Until the switches land, every one of these returns an ordinary live search.
await testScenario({ scenario: "priceChanged", hotel: "HC1" });
await testScenario({ scenario: "soldOut", supplier: "dida" });
await testScenario({ scenario: "serviceUnavailable", rawcache: "off" });
```

## Python Example

```python
import requests

def test_scenario(params=None):
    if params is None:
        params = {}

    test_header = "&".join([f"{k}={v}" for k, v in params.items()])

    headers = {
        'Authorization': f'Bearer {token}',
        'Session-Id': session_id,
        'Test': test_header,
        'Content-Type': 'application/json'
    }

    payload = {
        "destinationId": "804028047",
        "checkIn": "2026-02-15",
        "checkOut": "2026-02-17",
        "roomOccupancies": [{"adultCount": 2, "childrenAges": []}]
    }

    response = requests.post(
        'https://api-test.ttdbooking.com/api/search/hotelList',
        headers=headers,
        json=payload
    )

    return response.json()

test_scenario({'scenario': 'priceChanged', 'hotel': 'HC1'})
test_scenario({'scenario': 'soldOut', 'supplier': 'dida'})
```

## cURL Example

```bash
curl -X POST "https://api-test.ttdbooking.com/api/search/hotelList" \
  -H "Authorization: Bearer your-jwt-token" \
  -H "Session-Id: 374337a797454a344ad999c7730da01c" \
  -H "Test: scenario=soldOut&supplier=dida" \
  -H "Content-Type: application/json" \
  -d '{
    "destinationId": "804028047",
    "checkIn": "2026-02-15",
    "checkOut": "2026-02-17",
    "roomOccupancies": [{ "adultCount": 2, "childrenAges": [] }]
  }'
```

## Troubleshooting

#### The scenario never fires

Expected, for now — see the status notice at the top of this page. No scenario
is implemented, so the header changes nothing. It is not a typo in your header
and it is not the environment.

#### The request is rejected with `400 {"code":100000400}`

The body failed validation; the `Test` header is never the cause. The usual
culprit on search is `occupancy` in place of `roomOccupancies`, or
`roomOccupancies` omitted altogether — it is required and must carry at least
one entry. `Session-Id` is a required header on HotelRates, CheckAvail and Book.
See [Error handling](./error-handling) for the full business-code table.

## Security Considerations

- The `Test` header will be honoured only in the sandbox and test environments
- Production ignores test parameters it does not recognise
- Sandbox scenarios run against test data, separate from production systems

## Support and Resources

- **Technical Support**: `integrations@ttdbooking.com`
- **API Documentation**: Full reference at [developer.ttdbooking.com/hotel-api/docs](https://developer.ttdbooking.com/hotel-api/docs)
- **Test Environment**: `https://api-test.ttdbooking.com`

---

_This guide changes as the API does. Check the API documentation for the current reference._
