Adrasis™

Tours

Search, prebook, and book tours and excursions: shared seat-in-coach and private per-group offers, gated by operating days and seat allotment.

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.

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.