The Alps2Alps Public API is a free, key-less HTTP API that lets AI agents and developer integrations discover Alpine transfer routes, retrieve real-time prices from the same booking engine that powers the website, look up verified accommodation entries, and generate one-shot checkout links that land the end user directly on the booking form with everything pre-filled.
No authentication is required. All endpoints are rate-limited per IP. All responses are application/json.
https://booking.alps2alps.com/api/public/v1/https://booking.alps2alps.com/openapi/public-v1.json. Import it directly into Postman, Insomnia, or any AI agent framework that accepts an OpenAPI URL (OpenAI function calling, Anthropic tool use, LangChain, AutoGen, and others)./locations/search to resolve the user’s pickup and drop-off names into airport-… / resort-… / city-… codes./accommodations?resort_id=… once the resort side is known so the user can confirm a specific hotel. Always confirm the chosen entry with the user before sending its id./transfer-options with the location codes plus passenger, luggage, and date inputs. Present prices, vehicle types, travel time, and any promo discount to the user./checkout-link with the same body plus any optional extras (vehicle type id, flight number, accommodation id, driver notes).checkout_url is valid for 24 hours. Opening it lands the user on booking step 3 (Your Details) with all fields pre-filled. They only need to enter contact details and complete payment./api/public/v1/locations/searchSearch for supported pickup and drop-off locations: resorts, airports, train stations, and cities.
| Parameter | Required | Notes |
|---|---|---|
q | Yes | Search term. Strings shorter than 2 characters return an empty array. |
A flat array of matching locations. Resort codes follow the pattern resort-{id}; transport hub codes follow {type}-{id} (e.g. airport-1, train_station-7, city-48).
[
{ "code": "airport-1", "name": "Geneva Airport", "type": "airport", "country": "Switzerland" },
{ "code": "resort-11", "name": "Chamonix", "type": "resort", "country": "France" }
]
400 INVALID_PARAMS — q parameter missing entirely.curl "https://booking.alps2alps.com/api/public/v1/locations/search?q=cham"
/api/public/v1/accommodationsRead-only access to the verified accommodation catalogue used by the booking funnel’s hotel autocomplete. Results are scoped to a 10 km radius around the supplied resort.
| Parameter | Required | Default | Notes |
|---|---|---|---|
resort_id | Yes | — | Numeric resort id from a resort-{id} location code. |
q | No | "" | Substring filter on name (accent-insensitive). Max 100 chars. |
limit | No | 20 | Hard-capped at 50. |
{
"data": [
{
"id": 38959,
"name": "Clos 66",
"address": "66 Clos des Charmilles, Chamonix",
"latitude": 45.9123,
"longitude": 6.8694
}
],
"total": 4
}
total is the count before limit is applied, so the caller can tell when results were truncated.
Important: Only
idvalues returned by this endpoint may be passed into/checkout-linkasaccommodation_id. Free-typed hotel names are not accepted, ensuring every order receives a verified name and address pair.
400 INVALID_PARAMS — resort_id missing or not an integer.404 RESORT_NOT_FOUND — resort id is unknown, inactive, or has no coordinates.curl "https://booking.alps2alps.com/api/public/v1/accommodations?resort_id=11&q=clos&limit=5"
/api/public/v1/transfer-optionsReturns real-time prices for every bookable vehicle type on the requested route, in the requested currency, with the requested passenger and luggage configuration. Nothing is persisted — this is a quote-only endpoint.
Accepts application/json or application/x-www-form-urlencoded.
| Campo | Tipo | Required | Notes |
|---|---|---|---|
route_from_code | string | Yes | e.g. airport-1 |
route_to_code | string | Yes | e.g. resort-11 |
outbound_date | string | Yes | YYYY-MM-DD |
outbound_time_hours | int | Yes | 0–23 |
outbound_time_minutes | int | Yes | 0–59 |
outbound_selected_time_is_flight | int (0/1) | No | 1 = the time given is a flight arrival time |
is_return | int (0/1) | No (default 0) | When 1, all return_* fields are required |
adult_count | int | Yes | ≥ 1 |
children_count | int | No | |
infant_count | int | No | |
children_age_seat_count | int | No | Number of child-seat-aged children |
children_age_booster_count | int | No | Number of booster-seat-aged children |
luggage_count | int | No | |
skibag_count | int | No | |
has_ski_equipment | int (0/1) | No | |
currency_code | string | No (default EUR) | ISO 4217 currency code |
promo_code | string | No | Silently ignored if invalid |
For return trips, mirror the outbound fields with a return_ prefix: return_route_to_code, return_date, return_time_hours, return_time_minutes, return_selected_time_is_flight, return_adult_count, return_children_count, return_infant_count, return_children_age_seat_count, return_children_age_booster_count, return_luggage_count, return_skibag_count, return_has_ski_equipment.
{
"disclaimer": "Prices shown are real-time and calculated using the same engine as the booking website.",
"route": {
"from": "Geneva Airport",
"to": "Chamonix",
"distance_km": 99,
"duration_minutes": 100,
"travel_time": "01:40:00"
},
"currency": "EUR",
"outbound": {
"pick_up_date_time": "2026-07-22 14:30:00",
"vehicles": [
{ "vehicle_type_id": 2, "name": "Standard/economy", "price": 175, "offer_code": "requested" },
{ "vehicle_type_id": 10, "name": "Standard minivan", "price": 247, "offer_code": "requested" },
{ "vehicle_type_id": 4, "name": "VIP", "price": 418.50, "offer_code": "requested" }
]
},
"return": null,
"promo_code_applied": false
}
When a valid promo is applied, the response also includes:
"promo_code_discount": { "type": "percent", "value": 5 }
400 INVALID_PARAMS — body empty, validation failure, or malformed date.400 CURRENCY_NOT_SUPPORTED — currency not in the active currency list.404 ROUTE_NOT_FOUND — location code combination does not map to an active route.422 UNSUPPORTED_ROUTE — station-to-station, resort-to-resort, or other funnel-rejected combinations.422 MANUAL_BOOKING_REQUIRED — route requires manual handling.500 INTERNAL_ERROR — pricing engine threw an unrecognised exception.curl -X POST -H "Content-Type: application/json" \
-d '{
"route_from_code": "airport-1",
"route_to_code": "resort-11",
"outbound_date": "2026-07-22",
"outbound_time_hours": 14,
"outbound_time_minutes": 30,
"outbound_selected_time_is_flight": 1,
"is_return": 0,
"adult_count": 2,
"luggage_count": 2,
"currency_code": "EUR"
}' \
"https://booking.alps2alps.com/api/public/v1/transfer-options"
/api/public/v1/checkout-linkAccepts the same body as /transfer-options plus a few optional pre-fill fields. Returns a one-shot URL valid for 24 hours. Opening the URL lands the user on booking step 3 (Your Details) with all fields pre-filled — they only need to enter contact details and pay.
| Campo | Tipo | Notes |
|---|---|---|
outbound_vehicle_type_id | int | Optional. Defaults to the cheapest available outbound vehicle. |
return_vehicle_type_id | int | Optional. Only used when is_return = 1. |
outbound_flight_number | string | Optional. Alphanumeric + hyphen, max 16 chars. |
return_flight_number | string | Optional. Only used when is_return = 1. |
accommodation_id | int | Optional. Must be an id returned by /accommodations and within 10 km of the route’s resort. |
additional_info | string | Optional. Free-text driver note. Max 1000 chars. |
return_additional_info | string | Optional. Driver note for the return leg. Only used when is_return = 1. |
{
"checkout_url": "https://alps2alps.com/book/public-checkout/8f1c2c…",
"expires_at": "2026-05-28 09:14:22",
"currency": "EUR",
"promo_code_applied": true
}
All errors from /transfer-options, plus:
400 INVALID_PARAMS — accommodation_id is not a positive integer.400 VALIDATION_ERROR — accommodation id unknown, outside the route’s resort radius, or route has no resort side.422 NO_BOOKABLE_VEHICLE — no vehicle had a usable price on this route.500 INTERNAL_ERROR — could not persist the checkout link.curl -X POST -H "Content-Type: application/json" \
-d '{
"route_from_code": "airport-1",
"route_to_code": "resort-11",
"outbound_date": "2026-07-22",
"outbound_time_hours": 14,
"outbound_time_minutes": 30,
"outbound_selected_time_is_flight": 1,
"is_return": 0,
"adult_count": 2,
"luggage_count": 2,
"currency_code": "EUR",
"outbound_vehicle_type_id": 4,
"outbound_flight_number": "BA123",
"accommodation_id": 38959,
"additional_info": "Please call on arrival."
}' \
"https://booking.alps2alps.com/api/public/v1/checkout-link"
All errors share the same JSON envelope:
{ "error": { "code": "UNSUPPORTED_ROUTE", "message": "The routes from station to station is not supported" } }
| HTTP | Code | When |
|---|---|---|
| 400 | INVALID_PARAMS | Missing or invalid request fields, malformed dates, or validation failures. |
| 400 | CURRENCY_NOT_SUPPORTED | Currency not in the active currency list. |
| 400 | VALIDATION_ERROR | accommodation_id not found, not in range, or not applicable to this route. |
| 404 | RESORT_NOT_FOUND | /accommodations could not resolve the resort. |
| 404 | ROUTE_NOT_FOUND | Location code combination does not map to an active route. |
| 422 | UNSUPPORTED_ROUTE | Funnel rejects this destination-type combination (e.g. station-to-station). |
| 422 | MANUAL_BOOKING_REQUIRED | Route requires manual handling; not bookable online. |
| 422 | NO_BOOKABLE_VEHICLE | No vehicle had a usable price on this route. |
| 500 | INTERNAL_ERROR | Catch-all for all other unhandled exceptions. |
Pass any active ISO 4217 currency code in currency_code (e.g. EUR, GBP, CHF, USD). The default is EUR.
For non-EUR responses the disclaimer field in /transfer-options is extended to note that the exact checkout total may shift slightly due to live FX rates (sourced from the ECB, same as the booking website).
Pass promo_code in the request body on either /transfer-options or /checkout-link. The code is validated server-side. If validation fails or the promo service is temporarily unreachable, the code is silently ignored y promo_code_applied returns false — the request itself still succeeds. The caller can retry or surface the unapplied state to the user.
When a promo is applied on /transfer-options, the response includes promo_code_discount with a type (e.g. "percent") and value.
The API is browser-callable with no additional configuration:
Access-Control-Allow-Origin: *Access-Control-Allow-Headers: Content-Type, AcceptAccess-Control-Allow-Methods: GET, POST, OPTIONSOPTIONS preflight returns HTTP 204 with no body.