Skip to main content

Amadeus

Nexa integrates with Amadeus Self-Service APIs for hotel inventory search and booking. Amadeus is the largest GDS and one of the two primary inventory sources for the platform (the other is Hotelbeds).

Amadeus appears in two independent integrations in Nexa: as the hotel vendor described on this page, and — for airlines that run on Amadeus Altéa — as the PSS that supplies disruption events, manifests, and re-accommodation decisions (Airline systems). The two roles use different APIs, different credentials, and different adapters. A tenant may use one, both, or neither.

What we use it for

CapabilityAmadeus APINexa adapter
Hotel availability searchHotel Search APIAmadeusHotelProviderAdapter (IHotelProvider)
Hotel bookingHotel Orders APIAmadeusBookingProviderAdapter (IBookingProvider)
Booking cancellationHotel Orders API (DELETE)AmadeusBookingProviderAdapter.cancel

How it fits in the platform

Amadeus is one leg of the scatter-gather search — the booking module fans out to every configured inventory source in parallel and time-boxes the aggregation at 2 seconds. Whichever sources have responded by the cutoff are merged, deduplicated, and ranked. Slow Amadeus responses don't slow operators; they just don't appear in the result set for that search.

Authentication

Amadeus uses OAuth2 client credentials with token rotation:

  • Token endpoint: https://api.amadeus.com/v1/security/oauth2/token
  • Token TTL: 30 minutes (Amadeus-published).
  • Nexa caches the token until exp - 60s. On a 401, force-refresh once before propagating.

Credentials are tenant-managed — the airline holds the contract with Amadeus; Nexa stores the API key + secret in the tenant's Secret Manager namespace under nexa/<tenant>/vendor/amadeus/.

Rate limiting

Amadeus publishes per-customer TPS limits that depend on the airline's plan. The platform enforces the limit cluster-wide via the vendor-egress token bucket:

  • amadeus.search — typically 10 TPS
  • amadeus.booking — typically 5 TPS

The exact values are tenant-configured at onboarding. Burst beyond the configured TPS blocks at the worker level rather than calling and getting 429'd — the bus accumulates depth, the HPA scales worker count up to the bucket ceiling, and Amadeus never sees the burst.

Search behavior

POST /v1/hotels/search from the operator UI fans out to every adapter. The Amadeus adapter:

  1. Translates the Nexa search request (airport, check-in, check-out, rooms, tier) to Amadeus Hotel Search parameters.
  2. Calls Amadeus.
  3. Translates the response into the NexaInventoryObject canonical format — same field names, same units, same amenity vocabulary as every other adapter.
  4. Returns to the booking aggregator.

The mapper handles vendor-specific quirks: Amadeus's amenity codes map to Nexa's normalized WHEELCHAIR_ACCESSIBLE, FREE_BREAKFAST, etc. via amadeus.amenity.mapper.ts. Star ratings, distance-to-airport, and pricing tiers normalize at the same step.

Booking behavior

When the operator submits compensation, the booking workflow dispatches the work to the Amadeus adapter (selected by reading the partner from the offer URN), and:

  1. Waits for available budget under per-partner traffic shaping.
  2. Mints a stable Nexa-side reservation URN before calling Amadeus, so the URN survives retries and ambiguous timeouts.
  3. Calls Amadeus Hotel Orders with the Nexa reservation URN as the external_reference.
  4. On success, wraps the Amadeus confirmation as urn:reservation:<amadeus-id>:vendor:amadeus:status:confirmed and returns the canonical voucher payload.
  5. On failure, classifies the error (transient → retry; permanent → route to manual reconciliation).

Idempotency

Amadeus accepts an external_reference field on booking creation. Nexa supplies the Nexa-side reservation URN. Replays of the same IssueBooking command (e.g., after a worker crash) find the existing booking and return the same confirmation; no duplicate billing.

Cancellation

Cancellation goes through IBookingProvider.cancel(vendorConfirmationUrn). The adapter parses the URN, extracts amadeus, and dispatches to the Amadeus DELETE endpoint. The same idempotency model applies — replays return the same status.

Permanent-failure classification

Some Amadeus errors are not retryable:

Amadeus errorNexa classificationAction
NON_REFUNDABLE (cancel attempt)PermanentRoute to manual reconciliation, transition sub-case to COMPENSATION_FAILED, surface to operator.
BOOKING_PAST_CANCELLATION_DEADLINEPermanentSame as above.
RATE_NOT_AVAILABLE (book attempt)Permanent (this offer specifically)Mark the offer stale, return error to allow the operator to pick a different one.
INVALID_PAYMENT_INFOPermanentSurface to operator; payment method needs correction.
5xx, timeouts, network errorsTransientRetry with backoff.
429TransientRetry with longer backoff (token bucket should prevent this).

Permanent failures are surfaced to the operator with the original Amadeus error code in X-Vendor-Error-Code so manual reconciliation has the full context.

Mock mode

Every Amadeus adapter has a sibling mock at amadeus.mock.data.ts. In dev environments, the mock returns deterministic results (a fixed catalog of Santiago hotels with predictable prices), enabling integration testing without Amadeus credentials.

The flag is per-tenant: nexa/<tenant>/vendor/amadeus/mode = mock | live. Customer Success flips this once production credentials are validated.

Onboarding checklist

For a new tenant integrating Amadeus:

  • Tenant procures Amadeus Self-Service credentials (production tier).
  • Credentials loaded into nexa/<tenant>/vendor/amadeus/ Secret Manager namespace.
  • Tenant-specific TPS configured in amadeus.search.bucket and amadeus.booking.bucket.
  • Adapter health check passes against Amadeus production (GET /v1/security/oauth2/token succeeds, POST /v3/shopping/hotel-offers returns canonical results).
  • Mock-mode flag flipped to live.
  • First end-to-end booking against a sandbox case validated.

Onboarding takes 1–3 business days assuming credentials are in hand.

Compliance & data handling

Amadeus is a data sub-processor under Nexa's tenant DPAs. Per-passenger data sent to Amadeus is the minimum required for booking: lead-passenger name, contact, group size, room requirements. PII handling is governed by the airline's own data-sharing agreement with Amadeus — Nexa is the data processor, the airline is the controller, Amadeus is the sub-processor.

PNR and passport data do not flow through the Nexa Amadeus adapter for booking purposes — that data lives in the airline's PSS, not in the disruption-handling flow.

Was this helpful?