POST/v1/transfers/book

Book a transfer

Create a reservation from a priced offer.

Share
POST/v1/transfers/book

API console

Try it

Send a real request to the sandbox API and inspect the response.

Credentials

Log in to pick from your saved API keys instead of pasting them.

Request body

cURL request

cURL
bash
curl -X POST 'https://api.sandbox.travelandz.com/v1/transfers/book' \
  -H 'Authorization: Bearer YOUR_SECRET_KEY' \
  -H 'X-Travelandz-Id: YOUR_PUBLIC_KEY:YOUR_PROFILE_CODE' \
  -H 'Content-Type: application/json' \
  -d '{"gdsprovider":0,"bookingToken":"opaque_offer_token_generated_by_travelandz","pricingToken":"opaque_public_pricing_token_generated_by_travelandz","searchId":"73a5670b476649a985f0535db1077c05","resultId":"fe94b51ccd0623a9f1adabfbe0614d34","selectedAmenities":["baby_seats","child_booster"],"currency":"USD","email":"happytraveler@example.com","countryCodeName":"US","phoneNumber":"+18775998200","firstName":"Happy","lastName":"Traveler","airline":"AA","flightNumber":"123","customerSpecialInstructions":"My doorbell is broken, please call on arrival","partnerTrackingId":"1234567ABC","extraPaxInfo":[{"firstName":"Jose","lastName":"Smith"}]}'

Add your credentials to send a request.

This request needs identifiers or tokens from an earlier call. Run the previous step first, then paste its values here.

Response

Click "Try it!" to send a request and see the response here.

Create a reservation from a priced offer.

Authentication and headers

HeaderDescription
AuthorizationBearer <secret_key>. Keep the secret on the server and never write it to client logs.
X-Travelandz-Id<public_key>:<profile_code>, where the persisted profile code has the form dp_<12 alphanumeric>.
LANGPreferred locale header. Accept-Language is also supported.
Content-Typeapplication/json for requests with a JSON body.

Request

Send the bookingToken, pricingToken, searchId and resultId you already have, plus the traveller contact fields. selectedAmenities and currency must match what you sent to pricing.

When the offer has flightInfoRequired: true, airline and flightNumber are required. A round trip that needs flight details also requires returnAirline and returnFlightNumber. If you send ticketTypes, the total count must equal the main passenger plus the length of extraPaxInfo, so send extraPaxInfo too — an empty array for a single traveller.

Request Body Schema

gdsprovider
enum
0
Yes
Transfer content selector. Currently 0.
bookingToken
stringYes
Copy the bookingToken of the selected offer.
searchId
stringYes
Must be the searchId of the selected offer.
resultId
stringYes
Must be the resultId of the selected offer.
pricingToken
stringYes
Opaque value returned by pricing. Required to book.
selectedAmenities
arrayYes
selectedAmenities[]
string[]No
When sent, must match the priced selection exactly.
currency
enum
EURUSDINRCHFJPYGBPAUDCADCNYSGDNZDMXN
No
Lowercase values are accepted and normalized. Defaults to USD on a new search and is inherited afterwards.
email
string
Format: email
Yes
countryCodeName
string
Format: ISO 3166-1 alpha-2
Yes
For example US or ES.
phoneNumber
stringYes
Valid phone number including the country prefix.
firstName
stringYes
lastName
stringYes
customerSpecialInstructions
stringNo
partnerTrackingId
stringYes
Your own correlation identifier for this booking.
airline
string
Format: IATA (2 characters)
No
Required when the offer has flightInfoRequired: true. Send it together with flightNumber.
flightNumber
stringNo
Alphanumeric, 1-8 characters, no spaces.
returnAirline
stringNo
Required for a round trip that needs flight details. Send it together with returnFlightNumber.
returnFlightNumber
stringNo
Alphanumeric, 1-8 characters.
extraPaxInfo
arrayYes
extraPaxInfo[]firstName
stringYes
extraPaxInfo[]lastName
stringYes
extraPaxInfo[]email
string
Format: email
No
extraPaxInfo[]phoneNumber
stringNo
ticketTypes
arrayYes
ticketTypes[]id
stringYes
Ticket type identifier from the offer. Must be unique.
ticketTypes[]count
numberYes
Integer of at least 1.
scheduleIndex
numberNo
Index of the chosen alternative time. Must be 0 or greater.
paymentToken
stringNo
Only when the selected offer requires it.
successUrl
string
Format: URL
No
Only when the selected offer requires it.
language
enum
en-USes-ESde-DEfr-FRpt-BRzh-CNit-IT
No
Legacy field. Prefer the LANG or Accept-Language header.

Request example

json
json
{
  "gdsprovider": 0,
  "bookingToken": "opaque_offer_token_generated_by_travelandz",
  "pricingToken": "opaque_public_pricing_token_generated_by_travelandz",
  "searchId": "73a5670b476649a985f0535db1077c05",
  "resultId": "fe94b51ccd0623a9f1adabfbe0614d34",
  "selectedAmenities": [
    "baby_seats",
    "child_booster"
  ],
  "currency": "USD",
  "email": "happytraveler@example.com",
  "countryCodeName": "US",
  "phoneNumber": "+18775998200",
  "firstName": "Happy",
  "lastName": "Traveler",
  "airline": "AA",
  "flightNumber": "123",
  "customerSpecialInstructions": "My doorbell is broken, please call on arrival",
  "partnerTrackingId": "1234567ABC",
  "extraPaxInfo": [
    {
      "firstName": "Jose",
      "lastName": "Smith"
    }
  ]
}

Success response

Booking answers with HTTP 200 and a status field rather than 201, because the reservation is not always confirmed immediately.

Read status together with completed before you tell the traveller anything:

  • completed with completed: true and at least one reservation — the transfer is booked.
  • pending — no final answer yet. Read the reservation to find out how it ended; do not send the request again.
  • failed — the booking was refused. error explains why.

metadata.detailsIdentifier tells you which identifier to use when you read the reservation afterwards.

Response Body Schema

status
enum
completedpendingfailed
Yes
completed
booleanYes
Treat the operation as confirmed only when this is true and reservations is not empty.
timedOut
booleanYes
True when a final state was not reached in time.
reservations
arrayYes
reservations[]gdsprovider
enum
0
Yes
reservations[]reservationId
stringYes
Persist this value; reservation reads and cancellation need it.
reservations[]confirmationNumber
stringNo
Traveller-facing confirmation code.
reservations[]status
enum
completedpendingfailed
Yes
reservations[]cancelled
booleanYes
reservations[]totalAmount
numberYes
Total charged for the reservation.
reservations[]currency
enum
EURUSDINRCHFJPYGBPAUDCADCNYSGDNZDMXN
Yes
reservations[]pickupInstructions
stringNo
reservations[]ticketUrl
string
Format: URL
No
reservations[]selectedScheduleIndex
numberNo
reservations[]departureDatetime
string
Format: ISO 8601
No
reservations[]arrivalDatetime
string
Format: ISO 8601
No
reservations[]selectedAmenities
arrayYes
reservations[]selectedAmenities[]key
stringYes
Value to send in selectedAmenities.
reservations[]selectedAmenities[]name
stringYes
Localized name.
reservations[]selectedAmenities[]description
stringNo
reservations[]selectedAmenities[]imageUrl
string
Format: URL
No
reservations[]selectedAmenities[]pngImageUrl
string
Format: URL
No
reservations[]selectedAmenities[]inputType
enum
booleannumeric
No
reservations[]selectedAmenities[]included
booleanYes
True when the amenity is already part of the offer.
reservations[]selectedAmenities[]selectable
booleanYes
True when the amenity can be added to this offer.
reservations[]selectedAmenities[]selected
booleanYes
True when the amenity is part of the priced selection.
error
stringNo
Present when status is failed.
metadata
objectYes
metadatauseSearchIdForDetails
booleanYes
True when reservation details must be read with searchId instead of reservationId.
metadatadetailsIdentifier
enum
reservationIdsearchId
Yes
Identifier to use when reading the reservation.
metadatadetailsSearchId
stringNo
Present when detailsIdentifier is searchId.
metadatamessage
stringNo

Response examples

200 Booked

json
json
{
  "status": "completed",
  "completed": true,
  "timedOut": false,
  "reservations": [
    {
      "gdsprovider": 0,
      "reservationId": "f390daff1fdf4cccb19b7abd825dc011",
      "confirmationNumber": "TZ-6202191",
      "status": "completed",
      "cancelled": false,
      "totalAmount": 181.97,
      "currency": "USD",
      "pickupInstructions": "The driver will call you when he arrives.",
      "selectedScheduleIndex": 0,
      "departureDatetime": "2026-08-16T14:40:00-04:00",
      "arrivalDatetime": "2026-08-16T15:06:00-04:00",
      "selectedAmenities": [
        {
          "key": "baby_seats",
          "name": "Baby seats",
          "description": "Your vehicle will have a child safety seat to keep children under age 4 safe.",
          "imageUrl": "https://api.sandbox.travelandz.com/v1/assets/transfers/images/0/amenities/baby-seats.svg",
          "pngImageUrl": "https://api.sandbox.travelandz.com/v1/assets/transfers/images/0/amenities/baby-seats.png",
          "inputType": "numeric",
          "included": false,
          "selected": true,
          "selectable": true
        },
        {
          "key": "child_booster",
          "name": "Child booster",
          "description": "Your vehicle will have a child booster seat to keep children from age 4-8 safe.",
          "imageUrl": "https://api.sandbox.travelandz.com/v1/assets/transfers/images/0/amenities/child-booster.svg",
          "pngImageUrl": "https://api.sandbox.travelandz.com/v1/assets/transfers/images/0/amenities/child-booster.png",
          "inputType": "numeric",
          "included": false,
          "selected": true,
          "selectable": true
        }
      ]
    }
  ],
  "metadata": {
    "useSearchIdForDetails": true,
    "detailsIdentifier": "searchId",
    "detailsSearchId": "73a5670b476649a985f0535db1077c05",
    "message": "This booking includes amenities. Use searchId to retrieve complete reservation details."
  }
}

200 No final answer yet

json
json
{
  "status": "pending",
  "completed": false,
  "timedOut": true,
  "reservations": [],
  "metadata": {
    "useSearchIdForDetails": false,
    "detailsIdentifier": "reservationId"
  }
}

200 Refused

json
json
{
  "status": "failed",
  "completed": false,
  "timedOut": false,
  "reservations": [],
  "error": "The booking could not be completed",
  "metadata": {
    "useSearchIdForDetails": false,
    "detailsIdentifier": "reservationId"
  }
}

Errors

HTTPCodeMeaningRecommended action
400The body, query or path is invalid, or contains an unknown property.Fix the request using the message array.
400transfer_invalid_currencyThe currency is outside the supported list.Use a supported currency.
400transfer_invalid_languageThe requested language is not supported.Use one of the documented language values.
429transfer_provider_errorThe service is temporarily rate limited.Retry with exponential backoff.
502transfer_provider_errorThe request could not be completed.Do not assume success. Keep your identifiers and read the reservation when the operation could have been created.
400transfer_pricing_requiredThe request has no pricing token.Call pricing first, then send its pricingToken.
400transfer_invalid_booking_tokenThe booking token has expired, was modified, or does not belong to this offer.Search again and use the token of the newly selected offer.
400transfer_invalid_pricing_tokenThe pricing token is invalid or inconsistent with the rest of the request.Request pricing again and send the token it returns unchanged.
400transfer_invalid_amenitiesThe amenity keys are duplicated, empty, or unavailable for this offer.Send unique keys taken from the offer or from the amenity catalog.
400transfer_currency_mismatchThe currency does not match the offer, the quote or the reservation.Reuse the currency returned by the previous step, or omit the field to inherit it.
400transfer_flight_info_requiredThe offer requires airline and flightNumber.Send both flight fields when the offer has flightInfoRequired: true.
400transfer_return_flight_info_requiredA round trip requires the return flight details.Send returnAirline and returnFlightNumber.
409transfer_price_changedThe price of the offer is no longer the one that was quoted.Request pricing again and charge the new finalPrice.amount.
409transfer_booking_in_progressThe booking could not be accepted for this pricing token.Read the reservation before creating another one, so you never book twice.
410transfer_pricing_expiredThe quote expired before the booking was created.Search and price again.

Usage notes

Charge the traveller only the finalPrice.amount returned by pricing. If you receive transfer_price_changed, request pricing again and charge the new amount.

If a booking request fails with 502, do not assume it failed functionally: read the reservation with the identifiers you already hold before creating another one. Bookings that include amenities must be read by searchId.

Never log tokens, payment data or traveller personal data on the client.

cURL example

bash
bash
curl --request POST \
  --url "https://api.sandbox.travelandz.com/v1/transfers/book" \
  -H "Authorization: Bearer $TRAVELANDZ_SECRET_KEY" \
  -H "X-Travelandz-Id: $TRAVELANDZ_PUBLIC_KEY:$TRAVELANDZ_PROFILE_CODE" \
  -H "Content-Type: application/json" \
  --data '{
  "gdsprovider": 0,
  "bookingToken": "opaque_offer_token_generated_by_travelandz",
  "pricingToken": "opaque_public_pricing_token_generated_by_travelandz",
  "searchId": "73a5670b476649a985f0535db1077c05",
  "resultId": "fe94b51ccd0623a9f1adabfbe0614d34",
  "selectedAmenities": [
    "baby_seats",
    "child_booster"
  ],
  "currency": "USD",
  "email": "happytraveler@example.com",
  "countryCodeName": "US",
  "phoneNumber": "+18775998200",
  "firstName": "Happy",
  "lastName": "Traveler",
  "airline": "AA",
  "flightNumber": "123",
  "customerSpecialInstructions": "My doorbell is broken, please call on arrival",
  "partnerTrackingId": "1234567ABC",
  "extraPaxInfo": [
    {
      "firstName": "Jose",
      "lastName": "Smith"
    }
  ]
}'