> For the complete documentation index, see [llms.txt](https://adrasis.gitbook.io/developer/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://adrasis.gitbook.io/developer/transfers.md).

# Transfers

Search, prebook, and book airport and point-to-point transfers: shared per-passenger and private per-vehicle offers over a zone-to-zone route.

Transfers are a single-product vertical (`product_type` `2`) with the same three-step booking flow as accommodation: search, prebook, and book. The flow uses a route rather than a stay. A route is a zone pair (`from_zone` → `to_zone`) for a direction and a service date.

* **SHARED** offers price **per passenger**: an adult base plus age-resolved children.
* **PRIVATE** offers price **per vehicle**, independent of the passenger count.

All three endpoints require the `distribution:booking` scope.

## Step 1: Search

```
POST /api/v1/transfer/search
```

Returns priced offers for the route, direction, and party. `direction` is `1` for arrival or `2` for departure. `service_class` filters the result: `0` for both, `1` for private only, `2` for shared only. `vehicle_type_public_id` is optional and narrows private offers to one vehicle type. `currency_code` is required and must be a three-letter uppercase ISO 4217 code.

Both zones, `direction`, `service_date`, the party, `service_class`, `vehicle_type_public_id`, `currency_code` and `language` 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.

```bash
curl -s -X POST \
  https://ari.console.adrasis.com/api/v1/transfer/search \
  -H 'Authorization: Bearer eyJ...' \
  -H 'Content-Type: application/json' \
  -d '{
    "from_zone_public_id": "zn_Airport01",
    "to_zone_public_id": "zn_Hotel77",
    "direction": 1,
    "service_date": "2026-07-04",
    "adults": 2,
    "child_ages": [6],
    "service_class": 0,
    "currency_code": "EUR",
    "language": "en"
  }'
```

```json
{
  "offers": [
    {
      "allocation_id": "alc_7a9e4c82b31d605ff09428ac37e612bd",
      "from_zone_public_id": "zn_Airport01",
      "to_zone_public_id": "zn_Hotel77",
      "direction": 1,
      "service_class": 2,
      "service_date": "2026-07-04",
      "total_selling_rate": "54.00",
      "currency_id": 978,
      "currency_code": "EUR"
    }
  ],
  "dropped": [],
  "trace_id": "0f2c9d6e-7b1a-4c3e-9a2f-1d6e7b1a4c3e"
}
```

`total_selling_rate` is the party total, and `currency_code` states the currency it is denominated in. Transfer 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 route priced solely in another currency returns no offers rather than a converted amount; ask for that currency instead.

Rates the party could not be priced on (for example a child age outside a shared tariff) 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: a zone id may be wrong, the route may sit outside your catalogue, or it may have no supply. Those three deliberately share one code. Carry the chosen `allocation_id` and the exact route-search fields into prebook.

## Step 2: Prebook

```
POST /api/v1/transfer/prebook
```

Replays the exact route search, resolves and re-prices the chosen allocation, then mints a short-lived prebook token. A changed search boundary cannot select a different offer; a withdrawn or sold-out allocation returns `410 Gone`.

Send back the search request, not the offer. The example below searched with `service_class: 0` and no vehicle filter, so it prebooks the same way even though the chosen offer reports `service_class: 2`. Copying the offer's values 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`.

```bash
curl -s -X POST \
  https://ari.console.adrasis.com/api/v1/transfer/prebook \
  -H 'Authorization: Bearer eyJ...' \
  -H 'Content-Type: application/json' \
  -d '{
    "allocation_id": "alc_7a9e4c82b31d605ff09428ac37e612bd",
    "from_zone_public_id": "zn_Airport01",
    "to_zone_public_id": "zn_Hotel77",
    "direction": 1,
    "service_date": "2026-07-04",
    "adults": 2,
    "child_ages": [6],
    "service_class": 0,
    "currency_code": "EUR",
    "language": "en"
  }'
```

```json
{
  "match_status": "MATCHED",
  "prebook_token": "<PREBOOK_TOKEN>",
  "prebook_expires_at": "2026-07-01T12:30:00Z",
  "offer": { "total_selling_rate": "54.00", "currency_id": 978, "currency_code": "EUR" },
  "trace_id": "0f2c9d6e-7b1a-4c3e-9a2f-1d6e7b1a4c3e"
}
```

Inspect `match_status` before booking. `MATCHED` is safe to finalize; a moved price or unavailable offer is reported there exactly as for accommodation (see [The booking flow](/developer/booking-flow.md#match_status)).

## Step 3: Book

```
POST /api/v1/transfer/book
```

Verifies the prebook token and writes a single-product transfer booking. The `Idempotency-Key` header is **mandatory**. A replay returns `200`; a conflicting reuse returns `409` (see [Idempotency](/developer/idempotency.md)).

```bash
curl -s -X POST \
  https://ari.console.adrasis.com/api/v1/transfer/book \
  -H 'Authorization: Bearer eyJ...' \
  -H 'Idempotency-Key: 3b2a1c0d-5e6f-4a8b-9c0d-1e2f3a4b5c6d' \
  -H 'Content-Type: application/json' \
  -d '{
    "prebook_token": "<PREBOOK_TOKEN>",
    "contact": {
      "first_name": "Ada",
      "last_name": "Lovelace",
      "email": "ada@example.io",
      "phone": "+441234567890"
    },
    "agency_reference": "your-ref-12345"
  }'
```

```json
{
  "booking": {
    "public_id": "bk_Tf81nQ4p",
    "booking_number": 100731,
    "status": "CONFIRMED",
    "product_type": 2,
    "total_amount": "54.00",
    "currency_code": "EUR"
  },
  "trace_id": "0f2c9d6e-7b1a-4c3e-9a2f-1d6e7b1a4c3e"
}
```

## Cancellation

A transfer booking uses the canonical two-phase cancellation flow: `cancellation-quote`, then `cancel`, on `/bookings/{public_id}`. Accommodation uses the same flow. See [The booking flow](/developer/booking-flow.md#step-5-cancel-two-phase). To group a transfer with other bookings into one itinerary, see [Trip bundling](/developer/trip-bundling.md).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://adrasis.gitbook.io/developer/transfers.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
