Live and bookable — pre-production, and no payment
These endpoints work against real American Airlines inventory: a search returns real offers and you can create a real booking with a carrier PNR. Two limits are worth knowing before you build against them.
- Orders are pre-production. They are genuine reservations in the airline's pre-production system, not commercial tickets — nobody flies on them. Cancel what you create; anything left over expires on its own payment time limit.
- Payment and ticketing cannot complete. An order is created as an unpaid hold, which is the normal agency flow, but ticketing is inhibited on this IATA number, so
POST /v1/orders/{orderID}/commitreturns502. Everything up to and including the reservation works.
Shopping
Offer seat map
Full seat map for an offer — rows, availability, price bands and decoded seat features.
GET
/v1/offers/{offerID}/seatsRequires X-API-KeyReturns the airline's
SeatAvailability for one offer as a canonical SeatMap, ready to drive an interactive seat picker.> Currently failing at the gateway. Every call returns 502 americanairlines: seat availability failed: [41] Failed to get data from seats-offer-service. Verified across four fare families (Basic Economy, Main Cabin, Main Cabin Flexible, Premium Economy), on both shopped and priced offers, repeated — so it is neither a fare restriction nor a transient blip. This is Accelya's seat service, not the adapter: the request is built and routed correctly and the failure comes back from upstream. The shape below is what the endpoint returns when the service is available.The offer ID goes in the path and must be percent-encoded — same rule as the services endpoint. An order ID works here too: GET /v1/offers/AA001Y1XD7ZA6/seats returns the map for an existing booking.A live BCN→JFK Boeing 777-200 map comes back as 24 rows, 240 seats, 190 available, across eight price bands from 23 to 145 EUR. Features are decoded to a stable vocabulary: accessible, aisle, bassinet, blocked, bulkhead, exit_row, extra_legroom, no_window, restricted_recline, window.Buying a seat. Put the seat in the seats array of POST /v1/orders, alongside the flight. seat_id holds the human designator (17A); the adapter remembers the à-la-carte offer-item reference from this seat map and resolves it at booking time from segment + row + column, so passing row, column and segment_id is enough.> Known limitation. Assigning a *paid* seat to an order that already exists is currently rejected by the AA sandbox with [230000197] Referenced ID not found in message, across every request shape tried — most likely because paid-seat pre-booking is not enabled on that gateway's ACL. Reading seat maps works; post-booking assignment does not. Sell seats inside OrderCreate.Results are cached per offer ID.Request example
curl --request GET \
--url https://api.norba.io/v1/offers/{offerID}/seats \
--header "X-API-Key: $NORBA_KEY"Response example
Response example
{
"flight_id": "AA-P2E80EC16-51FD-48AD-924B-1",
"airline": "AA",
"aircraft": "772",
"rows": 24,
"seats": [
{
"seat_id": "17A",
"row": 17,
"column": "A",
"cabin": "Economy",
"available": true,
"price": {
"amount": 128.93,
"currency": "EUR"
},
"features": [
"window",
"extra_legroom"
],
"segment_id": "SGM010012275a20c"
},
{
"seat_id": "17B",
"row": 17,
"column": "B",
"cabin": "Economy",
"available": false,
"price": {
"amount": 0,
"currency": "EUR"
},
"features": [
"blocked"
],
"segment_id": "SGM010012275a20c"
}
]
}Path parameters
offerIDstringRequiredCanonical offer ID or order ID. Percent-encode it.
Example:
AA-P2E80EC16-51FD-48AD-924B-1|P2E80EC16-51FD-48AD-924B-1-1Query parameters
airlinestringIATA code. Inferred from the ID prefix when omitted.
Example:
AAResponse fields
flight_idstringRequiredFlight or offer reference the map belongs to.
airlinestringRequiredIATA airline code.
aircraftstringAircraft type code, e.g.
772.rowsintegerRequiredNumber of rows in the map.
seats[].seat_idstringRequiredHuman seat designator, e.g.
17A.seats[].rowintegerRequiredRow number.
seats[].columnstringRequiredColumn letter.
seats[].cabinstringCabin name.
seats[].availablebooleanRequiredWhether the seat can be selected.
seats[].priceobject{amount, currency} — 0 when free.seats[].featuresarray<string>accessible, aisle, bassinet, blocked, bulkhead, exit_row, extra_legroom, no_window, restricted_recline, window.seats[].segment_idstringRequiredThe segment this seat is on. Required when you buy the seat.
Error codes
400unknown airline — no recognisable prefix and no ?airline=.502The airline rejected the reference.