2. Guides
Test More Scenarios
Status: not yet available
The
Testheader 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 withTest: scenario=soldOutis served as an ordinary live search against your enabled suppliers — the same response you would get with noTestheader at all.Do not treat a scenario run as evidence that your unhappy-path handling works. A
soldOutorserviceUnavailablerequest 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:
Test: key1=value1&key2=value2&key3=value3Basic Syntax
Test: scenario=priceChanged&hotel=HC1Multiple Parameters
Test: scenario=soldOut&hotel=HC1&supplier=dida&rawcache=offSending 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 enabledrawcache=off: caching disabled — always retrieve fresh datarawcache=bypass: skip the cache for this request onlyrawcache=only: serve from cache only; do not call the supplier
rawttl sets how long the cached entry lives:
Test: scenario=available&rawttl=300s
Test: scenario=available&rawttl=1h
Test: scenario=available&rawttl=2dScoping Parameters
hotel points a scenario at one property, supplier at one supplier
connection:
Test: scenario=soldOut&hotel=HC1
Test: scenario=serviceUnavailable&supplier=dida
Test: scenario=priceChanged&supplier=derbysoftRequest 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
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
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
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
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
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
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 for the full business-code table.
Security Considerations
- The
Testheader 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
- Test Environment:
https://api-test.ttdbooking.com
This guide changes as the API does. Check the API documentation for the current reference.

