Getting started

Errors

Errors use standard HTTP status codes and a stable, machine-readable error.code. Branch on the code; show the message to people.

Error shape

Response · 409
{
  "data": null,
  "meta": {},
  "error": {
    "code": "rate_unavailable",
    "message": "This selected rate is no longer available. Refresh the hotel rates and choose another option.",
    "details": []
  }
}

details is always an array. It lists each failed rule when a body or query fails validation, and is usually empty otherwise — including for other 400s that come back as validation_error, where message gives the reason.

Authentication and access

StatusCodeMeaningWhat to do
401unauthorizedKey missing (message Unauthorized), unknown, revoked or expired, or your agency is suspended or its API access is switched off.Check the key; create a new one if needed. If the key is right, contact support.
403forbiddenThe resource belongs to another agency, or your key's access level doesn't allow the call.Use a resource your agency owns, or an agency-admin key for key management.
403api_key_owner_missingThe key was created before keys recorded who created them, so it can't search or book.An agency admin creates a new key and you switch to it.
403agreement_unsignedYour agency hasn't signed the distribution agreement.An agency admin signs it in the portal.

Validation

StatusCodeMeaningWhat to do
400validation_errorThe body or query failed validation; details lists each problem, including unknown fields. Other rejected requests — a bad market on capabilities, say — also use this code, with an empty details and the reason in message.Fix the request.
400invalid_cursorThe search-results cursor is malformed. Other lists report a bad cursor as validation_error.Use the cursor exactly as returned.
400invalid_limitlimit on search results isn't a positive integer.Send a positive integer; values above 500 are capped at 500.
400unknown_destinationAn activity destination name couldn't be resolved.Send destinationCode from GET /destinations.
400invalid_hotel_selectionhotelId was sent on a non-hotel search.Remove it.
400invalid_product_typeA hotel-only call was made on another product type.Use the product rates route.
404not_foundThe ID doesn't exist, or has been purged.Check the ID.

Search and quotes

StatusCodeMeaningWhat to do
410search_expiredThe search has passed its 20-minute life. Opening a rate sheet or price-checking restarts the clock. Booking can return it too, once the search behind the quote is gone.Run a new search.
410quote_expiredThe quote's 20-minute life has ended.Fetch fresh rates and price-check again.
409quote_invalidThe quote has no usable price.Fetch fresh rates.
409unknown_supplierThe quote's inventory source can't be reached for a price-check right now.Choose another rate.
409rate_unavailableThe rate has sold out or is no longer offered.Refresh the rate sheet and let the traveller choose again.
409pax_mix_unavailableAn activity isn't available for the new traveller mix.Choose another option.
400activity_recheck_unsupportedThe activity has no separate options to list.Price-check the row directly.
400rate_option_not_offeredThe supplierRateRef sent with a price-check isn't one of this quote's options.Send a token from this quote's activity options, unchanged.
409price_check_currency_unavailableThe live price came back in a currency we can't convert to the quote's currency.Choose another rate, or search again.
409price_check_conflictAnother price-check on the same quote finished first.Retry once.
409quote_not_repriceableThe quote has already been booked or has expired.Start from fresh rates.
503supplier_unavailableThe inventory source didn't answer in time.Retry with backoff, or choose another rate.

Bookings

StatusCodeMeaningWhat to do
400idempotency_key_requiredNo Idempotency-Key header.Send a fresh UUID.
409idempotency_in_progressThat key is still running, or was used with a different body.Wait and retry, or use a new key for a new body.
409quote_not_price_checkedThe quote wasn't price-checked in the last 10 minutes, or another booking already claimed it.Price-check, then book straight away.
400changes_ack_requiredThe price-check reported a price or policy change you haven't acknowledged.Show the change, then send changesAcknowledged: true.
400package_ack_requiredThe rate may only be sold as part of a package.Send packageRateAcknowledged: true only if you are selling it in a package.
400traveler_manifest_mismatchTravellers don't match the rooms, adults and child ages you searched for.Send one traveller per searched guest with the right roomIndex and child ages.
400supplier_contact_requiredThis inventory needs a valid email and a phone number for the lead traveller, and one is missing.Always send both on travelers[0].
400traveler_title_requiredThis rate needs a title — on every traveller for a hotel quote with requiresGuestTitle: true, or on the lead traveller for some activities and transfers — and one is missing or not recognised. Refused before anything is charged.Send title as one of Mr, Mrs, Ms, Miss, Master, Dr. See Titles.
400travel_documents_requiredA flight passenger is missing a name, date of birth, gender, passport number, passport expiry or nationality, or their passport expires within 6 months of travel. message names the traveller. Refused before anything is charged.Complete the passenger's details, or ask them for a passport valid long enough.
400transfer_flight_details_requiredThe transfer needs the flight (arriving or departing).Send carrierName and flightNumber, at most 7 characters, like EK003.
400pan_requiredThe activity rate needs an Indian PAN (details.panRequired is true) and panNumber is missing or malformed.Send panNumber like ABCDE1234F.
400unsupported_payment_methodThe payment method isn't available for this booking.Send paymentMethod: "credit".
400booking_answer_requiredA mandatory booking question wasn't answered.Answer every question in details.bookingQuestions.
400booking_answer_invalidAn answer isn't one of the allowed answers, or is too long.Send one of the question's allowed answers, within its length limit.
400hold_not_eligibleThe rate can't be held — holds need a fully refundable hotel rate with a future free-cancellation deadline.Book and pay now instead.
409supplier_disabledThat inventory has been switched off since you searched.Choose another rate.
409live_supplier_booking_blockedSandbox only. Some inventory has no test environment, so outside production it only books rates that are still free to cancel. The rate is non-refundable or its free-cancellation window has closed. Never returned in production.Pick a rate that's still free to cancel.
409booking_invalid_transitionThe booking can't move to that state — cancelling a failed booking, for example.Read the booking's current state first.

Payment and credit

StatusCodeMeaningWhat to do
402credit_limit_exceededYour agency's available credit doesn't cover the booking.Top up or raise your limit in the portal.
403credit_disabledCredit payments are switched off for your agency.Contact support.
409wallet_currency_mismatchThe booking currency differs from your wallet currency.Search in your wallet currency.
409hold_payment_unsupportedA hold was paid with a method other than credit.Pay the hold with paymentMethod: "credit".
409payment_operation_in_progressAnother payment step on this booking is still running.Wait a few seconds, then read the booking before retrying.
409payment_authentication_pendingA card authentication was never completed. Card payments aren't available through the API.Pay with credit.

Rate limiting and platform

StatusCodeMeaningWhat to do
429rate_limitedToo many requests for this key in the last minute.Wait for Retry-After seconds.
409conflictA generic conflict with no more specific code; message says what.Read the resource's current state before retrying.
410goneA generic "no longer available" with no more specific code.Start again from fresh data.
500internal_errorSomething failed on our side.Retry with backoff; contact support with the time and endpoint if it persists.