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
Basket quote
The whole checkout total — fare plus seats and ancillaries, at the price you will actually be charged.
POST
/v1/offers/quoteRequires X-API-KeyPOST /v1/offers/price prices the fare alone, because at that point nothing else has been chosen. Everything added afterwards — a seat, a bag — changes the total by more than its own sticker price whenever your agency's fee is a percentage, so adding up line items yourself gets a smaller number than the one the order will actually carry. This endpoint runs the same pricing engine that will charge the order, so the number you show at checkout and the number on the order agree.Cheap to call on every basket change. It reserves nothing and calls no airline — it re-prices an offer this API has already priced, from the same catalogue snapshot POST /v1/offers/price and GET /v1/offers/{offerID}/seats / /services served for it. Seat and ancillary prices always come from that catalogue, never from numbers the client sends; an extra it cannot price answers 422, not a quote built on a guess.Requires a key with an agency behind it — a static PUBLIC_API_KEYS entry is refused, the same as every other commerce write.Request example
curl --request POST \
--url https://api.norba.io/v1/offers/quote \
--header "X-API-Key: $NORBA_KEY" \
--header "Content-Type: application/json" \
--data '{ "offer_id": "AA-P2E80EC16-51FD-48AD-924B-1|P2E80EC16-51FD-48AD-924B-1-1", "seats": [{ "segment_id": "SGM010012275a20c", "row": 17, "column": "A" }], "ancillaries": [{ "ancillary_offer_id": "SRVDEF08001b075a14f" }] }'Response example
Response example
{
"currency": "EUR",
"base_fare": 193,
"taxes_fees": 187.62,
"fare_total": 380.62,
"extras": 128.93,
"service_fee": 12.74,
"service_fee_components": [
{
"label": "Completed booking",
"amount": 9.52
},
{
"label": "Seat selection",
"amount": 3.22
}
],
"total": 522.29
}Request body
offer_idstringRequiredThe priced offer ID, from
POST /v1/offers/price. Required — an empty value returns 400 offer_id is required.Example:
AA-P2E80EC16-51FD-48AD-924B-1|P2E80EC16-51FD-48AD-924B-1-1seatsarray<Seat>Seats you intend to buy, from
GET /v1/offers/{offerID}/seats. Priced from that catalogue, not from any price you send here.ancillariesarray<Ancillary>Ancillaries you intend to buy, from
GET /v1/offers/{offerID}/services. Same rule: priced from the catalogue this API served.Response fields
currencystringRequiredISO 4217 code.
base_farenumberRequiredThe airline's base fare, unchanged.
taxes_feesnumberRequiredThe airline's taxes and carrier fees, unchanged.
fare_totalnumberRequiredbase_fare + taxes_fees.extrasnumberRequiredWhat the seats and ancillaries cost at the airline's own prices.
service_feenumberRequiredYour agency's charge on the whole basket — the fare plus every extra, at the rate on your plan.
service_fee_componentsarrayThe service fee broken into its labelled lines, when there is more than one.
totalnumberRequiredfare_total + extras + service_fee — the figure the order will actually carry.Error codes
400offer_id is required.404The offer was never priced through this API, or the price has expired — price it again before quoting.
422A requested seat or ancillary is not in the catalogue this API served for the offer, so it cannot be priced.