Tours are a single-product vertical (product_type 3) following the same
search → prebook → book rhythm, on a departure date for a tour and one of
its modalities.
- SIC (seat-in-coach) offers price per passenger: an adult base plus age-resolved children.
- PRIVATE offers price per group for the matching group-size tier.
Offers are gated by the modality's operating-days calendar and, for
allotment-managed modalities, by the seats remaining on the departure. All
three endpoints require the distribution:booking scope.
Step 1: Search
POST /api/v1/tour/search
Returns priced offers for the tour on the departure date. modality_public_id
is optional: omit it to price every modality, or pass it to narrow to one.
service_class filters: 0 both, 1 private only, 2 SIC only.
currency_code is required and must be a three-letter uppercase ISO 4217
code.
tour_public_id, modality_public_id, departure_date, the party,
service_class, currency_code, language and country_code are all bound
into the allocation_id. Prebook replays this request, so every one of them
must be repeated there exactly as you sent it here. language is a BCP 47 tag such as tr-TR; the server canonicalizes its casing, a malformed tag answers 400, and a well-formed tag the catalogue does not carry falls back to the default language.
curl -s -X POST \
https://ari.console.adrasis.com/api/v1/tour/search \
-H 'Authorization: Bearer eyJ...' \
-H 'Content-Type: application/json' \
-d '{
"tour_public_id": "tr_Bosphorus",
"departure_date": "2026-07-04",
"adults": 2,
"child_ages": [8],
"service_class": 0,
"currency_code": "EUR",
"language": "en"
}'
{
"offers": [
{
"allocation_id": "alc_159d722b4a763ebc54fd88a2106c139e",
"tour_public_id": "tr_Bosphorus",
"modality_public_id": "md_morning",
"service_class": 2,
"has_pickup": true,
"departure_date": "2026-07-04",
"total_selling_rate": "120.00",
"currency_id": 978,
"currency_code": "EUR"
}
],
"dropped": [],
"trace_id": "0f2c9d6e-7b1a-4c3e-9a2f-1d6e7b1a4c3e"
}
currency_code states the currency total_selling_rate is denominated in. Tour search
does not convert: it returns only rates already held in the currency you asked
for, so currency_code always equals the requested currency_code. A modality
priced solely in another currency returns no offers rather than a converted
amount; ask for that currency instead.
Exact remaining seat counts are not part of the partner contract. A returned
offer has enough inventory for the requested party. Offers that fall on a
non-operating weekday, are sold out, or cannot price the party are returned
under dropped rather than failing the request.
Branch on dropped[].reason_code, not on the sentence in reason. When the
response carries no offers and a single no_rate entry, nothing the request
named has a live rate for that date: the tour id may be wrong, it may sit
outside your catalogue, or the departure may have no supply. Those three
deliberately share one code.
Step 2: Prebook
POST /api/v1/tour/prebook
Replays the exact tour search, resolves and re-prices the chosen allocation,
re-applies the operating-days and seat gates, and mints a short-lived prebook
token. A changed search boundary cannot select another modality; a withdrawn
or sold-out allocation returns 410 Gone.
Send back the search request, not the offer. The example below searched every
modality, so it prebooks with modality_public_id still absent even though the
chosen offer reports md_morning. Copying the offer's modality into the
prebook body describes a narrower search than the one that priced the offer,
which mints a different allocation_id, matches nothing, and returns
410 Gone. The same holds for service_class.
curl -s -X POST \
https://ari.console.adrasis.com/api/v1/tour/prebook \
-H 'Authorization: Bearer eyJ...' \
-H 'Content-Type: application/json' \
-d '{
"allocation_id": "alc_159d722b4a763ebc54fd88a2106c139e",
"tour_public_id": "tr_Bosphorus",
"departure_date": "2026-07-04",
"adults": 2,
"child_ages": [8],
"service_class": 0,
"currency_code": "EUR",
"language": "en"
}'
{
"match_status": "MATCHED",
"prebook_token": "<PREBOOK_TOKEN>",
"prebook_expires_at": "2026-07-01T12:30:00Z",
"offer": {
"allocation_id": "alc_159d722b4a763ebc54fd88a2106c139e",
"tour_public_id": "tr_Bosphorus",
"modality_public_id": "md_morning",
"service_class": 2,
"has_pickup": true,
"departure_date": "2026-07-04",
"total_selling_rate": "120.00",
"currency_id": 978,
"currency_code": "EUR"
},
"trace_id": "0f2c9d6e-7b1a-4c3e-9a2f-1d6e7b1a4c3e"
}
Step 3: Book
Book requires your partner account to settle on account with the seller. Without
those terms it returns 422 PAYMENT_INTENT_NOT_SUPPORTED before writing the
booking. An optional payment_intent_kind may confirm the resolved INVOICE
intent; it cannot select different terms. Omit it to use your account's terms.
Search results and a prebook token do not replace this book-time check. See
Booking payment terms.
POST /api/v1/tour/book
Verifies the prebook token and writes a single-product tour booking. For an
allotment modality, the departure's seats decrement atomically. A seat race
between prebook and book returns 410 Gone. The Idempotency-Key header is
mandatory (replay → 200, conflict → 409; see
Idempotency).
curl -s -X POST \
https://ari.console.adrasis.com/api/v1/tour/book \
-H 'Authorization: Bearer eyJ...' \
-H 'Idempotency-Key: 6c5b4a39-2e1f-4a8b-9c0d-1e2f3a4b5c6d' \
-H 'Content-Type: application/json' \
-d '{
"prebook_token": "<PREBOOK_TOKEN>",
"contact": {
"first_name": "Ada",
"last_name": "Lovelace",
"email": "ada@example.io"
},
"agency_reference": "your-ref-12345"
}'
{
"booking": {
"public_id": "bk_To52pZ9k",
"booking_number": 100742,
"status": "CONFIRMED",
"product_type": 3,
"total_amount": "120.00",
"currency_code": "EUR"
},
"trace_id": "0f2c9d6e-7b1a-4c3e-9a2f-1d6e7b1a4c3e"
}
Cancellation
A tour booking cancels through the canonical two-phase cancel on
/bookings/{public_id}. See
The booking flow. To group a tour
with other bookings into one itinerary, see Trip bundling.