Availability and Quoting¶
Before creating an order you need a package (ctgId) and a price. The fastest way to get both is to request a quote — it resolves the correct package for the route, traveller age, and altitude, and returns the exact amount payable.
The catalogue endpoints are there for browsing and for building your own selection UI.
POST /reference/quote¶
Prices a trip and returns the recommended package.
Authentication: required.
One traveller per quote
A quote covers exactly one person. ages must contain exactly one value. To price a group, request one quote per traveller and sum the results.
Request¶
POST /api/external/v1/reference/quote
Authorization: Bearer <accessToken>
Content-Type: application/json
| Field | Type | Required | Validation |
|---|---|---|---|
nationality |
String | Yes | Non-blank, max 100 characters |
ages |
Integer[] | Yes | Exactly one age, each 1–120 |
startDate |
Date | Yes | YYYY-MM-DD |
endDate |
Date | Conditional | Required if duration is omitted |
duration |
Integer | Conditional | Required if endDate is omitted. Positive integer, in days |
routeId |
UUID | No | A known route. See GET /reference/routes |
maxAltitude |
Integer | Conditional | Required when routeId is omitted. 0–9000 metres |
numberOfPersons |
Integer | No | Deprecated. If sent, must be 1. Omit it |
You must supply the trip length exactly one way — endDate or duration — and the altitude exactly one way — routeId or maxAltitude. Passing routeId is preferred: it resolves the altitude for you and returns a route name you can show the customer.
{
"nationality": "American",
"ages": [28],
"routeId": "550e8400-e29b-41d4-a716-446655440000",
"startDate": "2026-10-01",
"duration": 14
}
Response¶
200 OK
{
"success": true,
"message": "Quote generated successfully",
"data": {
"quoteId": "11111111-1111-1111-1111-111111111111",
"quoteStatus": "ACTIVE",
"createdAt": "2026-07-07T03:30:00Z",
"ctgId": "8d9f0e5a-1234-4f2e-bc3a-6b1a2c4d5e6f",
"ctgCode": "CTG/TOURIST/MIDDLE",
"ctgName": "Tourist – Middle Altitude",
"nationality": "American",
"numberOfPersons": 1,
"ages": [28],
"routeId": "550e8400-e29b-41d4-a716-446655440000",
"routeName": "Annapurna Base Camp",
"maxAltitude": 4130,
"startDate": "2026-10-01",
"endDate": "2026-10-14",
"durationDays": 14,
"totalAmount": 590.00,
"insuranceCompany": "Example Insurance",
"coverage": [
{ "code": "LIB_DEATH", "name": "Accidental Death and Disability", "coverageAmount": 20000.00 },
{ "code": "LIB_MEDICAL", "name": "Accidental Medical Treatment", "coverageAmount": 3500.00 },
{ "code": "LIB_TRANSPORT", "name": "Emergency Medical Transportation", "coverageAmount": 8000.00 },
{ "code": "LIB_REPATRIATE", "name": "Repatriation of Corpse", "coverageAmount": 2000.00 }
],
"includedDevices": [
{
"deviceId": "a1b2c3d4-5678-4abc-9def-0123456789ab",
"name": "Tracer M3",
"description": "CTG tracer device with emergency SOS for high-altitude routes",
"quantity": 1,
"priceForDuration": 40.00
}
]
},
"timestamp": "2026-07-07T03:30:00Z"
}
| Field | Type | Description |
|---|---|---|
quoteId |
UUID | Pass back as quoteId when creating the order |
quoteStatus |
String | Quote status |
createdAt |
Timestamp | When the quote was generated |
ctgId |
UUID | Recommended package. Pass back as ctgId when creating the order |
ctgCode |
String | Package display code |
ctgName |
String | Package display name |
nationality |
String | Echoed from the request |
numberOfPersons |
Integer | Always 1 |
ages |
Integer[] | Echoed from the request |
routeId |
UUID | Resolved route |
routeName |
String | Resolved route name |
maxAltitude |
Integer | Route maximum altitude in metres |
startDate |
Date | Coverage start, inclusive |
endDate |
Date | Coverage end, inclusive |
durationDays |
Integer | Trip length in days |
totalAmount |
Decimal | Total payable for this quote |
insuranceCompany |
String | Underwriter display name |
coverage |
Object[] | Liability coverages: code, name, coverageAmount |
includedDevices |
Object[] | Bundled devices: deviceId, name, description, quantity, priceForDuration |
The quote is a complete order blueprint
You do not need a catalogue lookup between quoting and ordering. Map the quote straight onto the order:
| Quote field | Order field |
|---|---|
ctgId |
ctgId |
quoteId |
quoteId |
routeId |
routeId |
startDate |
departureDate |
Dropping an included device¶
includedDevices are bundled into totalAmount. To exclude one, pass its deviceId in excludedIncludedDeviceIds when you create the order. The order total is recalculated accordingly.
Examples¶
curl -X POST https://api.himalayanguardian.com/api/external/v1/reference/quote \
-H "Authorization: Bearer $HGN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"nationality": "American",
"ages": [28],
"routeId": "550e8400-e29b-41d4-a716-446655440000",
"startDate": "2026-10-01",
"duration": 14
}'
const res = await fetch(`${BASE_URL}/reference/quote`, {
method: "POST",
headers: {
Authorization: `Bearer ${await getAccessToken()}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
nationality: "American",
ages: [28],
routeId: "550e8400-e29b-41d4-a716-446655440000",
startDate: "2026-10-01",
duration: 14,
}),
});
const { data: quote } = await res.json();
console.log(quote.ctgName, quote.totalAmount);
res = requests.post(
f"{BASE_URL}/reference/quote",
headers={"Authorization": f"Bearer {access_token}"},
json={
"nationality": "American",
"ages": [28],
"routeId": "550e8400-e29b-41d4-a716-446655440000",
"startDate": "2026-10-01",
"duration": 14,
},
timeout=10,
)
res.raise_for_status()
quote = res.json()["data"]
print(quote["ctgName"], quote["totalAmount"])
Errors¶
| Status | Cause |
|---|---|
400 |
Validation failure — more than one age, age out of range, missing both endDate and duration, missing both routeId and maxAltitude, or numberOfPersons other than 1 |
401 |
Missing or invalid token |
404 |
routeId does not match a known route |
A validation failure returns field-level detail. See Errors.
GET /reference/ctgs¶
Lists the active public package catalogue. Use this to build a browse-and-select UI, or to look up package detail you want to display alongside a quote.
Authentication: required.
Query parameters¶
| Name | Type | Default | Description |
|---|---|---|---|
search |
String | — | Free-text search |
altitudeBand |
String | — | Filter by altitude band |
durationBand |
String | — | Filter by duration band |
ageBand |
String | — | Filter by age band |
productType |
String | — | Filter by insurance product type |
page |
Integer | 0 |
Zero-based page index |
size |
Integer | 20 |
Page size, capped at 100 |
sortBy |
String | displayOrder |
Sort field |
sortDir |
String | asc |
asc or desc |
Response¶
200 OK — data is a paginated result whose content array holds package objects.
| Field | Type | Description |
|---|---|---|
ctgId |
UUID | Package ID for quoting and ordering |
ctgCode |
String | Display code |
ctgName |
String | Display name |
insuranceProductId |
String | Underlying insurance product ID |
routeId |
UUID | Linked route, for special-route products |
insuranceCompany |
String | Underwriter display name |
minAltitude |
Integer | Altitude band lower bound, metres |
maxAltitude |
Integer | Altitude band upper bound, metres |
baseDurationDays |
Integer | Base duration |
minAge |
Integer | Minimum eligible age |
maxAge |
Integer | Maximum eligible age |
baseCtgPrice |
Decimal | Stored base/display price |
ctgPriceForDuration |
Decimal | Price calculated for the duration |
includedDevicesPrice |
Decimal | Mandatory included-device price |
totalPrice |
Decimal | Total public listing price |
liabilities |
Object[] | Liability coverages |
includedDevices |
Object[] | Included product devices |
description |
String | Product description |
termsConditions |
String | Terms summary or link |
curl -G https://api.himalayanguardian.com/api/external/v1/reference/ctgs \
-H "Authorization: Bearer $HGN_TOKEN" \
--data-urlencode "search=tourist" \
--data-urlencode "size=50"
Listed price vs. quoted price
totalPrice here is the public listing price for the package. The amount your customer actually pays is totalAmount from POST /reference/quote, which accounts for the specific traveller, route, and dates. Always charge against the quote.
GET /reference/routes¶
Lists active trekking routes. Only active routes are returned — there is no parameter to include inactive ones.
Authentication: required.
Query parameters¶
| Name | Type | Default | Description |
|---|---|---|---|
search |
String | — | Free-text search |
region |
String | — | Filter by region |
trekName |
String | — | Filter by trek name |
routeType |
String | — | Filter by route type |
routeCategory |
String | — | Filter by route category |
page |
Integer | 0 |
Zero-based page index |
size |
Integer | 20 |
Page size, capped at 100 |
sortBy |
String | name |
Sort field |
sortDir |
String | asc |
asc or desc |
Response¶
200 OK — data is a paginated result whose content array holds route summary objects. These are the same route summaries the public booking widget uses.
The field you need for the rest of the flow is routeId, which you pass to POST /reference/quote and then to POST /orders. Routes are also filterable by region, trek name, route type, and route category, as shown above.
curl -G https://api.himalayanguardian.com/api/external/v1/reference/routes \
-H "Authorization: Bearer $HGN_TOKEN" \
--data-urlencode "region=Annapurna" \
--data-urlencode "sortBy=name"
This endpoint uses a different pagination envelope
GET /reference/routes wraps its results in a different page envelope from GET /reference/ctgs and GET /travellers. All three expose a content array; the surrounding metadata field names differ. If you share one pagination helper across endpoints, read content and avoid depending on the metadata field names.
Custom routes¶
If a trip does not follow a catalogued route, you can skip routeId entirely and create the order with a customRouteName instead. See Booking. Quotes still need either a routeId or a maxAltitude.