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}/commit returns 502. Everything up to and including the reservation works.
Shopping

Price offer

Confirm the price with the airline and mint the bookable offer ID. Mandatory before booking.

POST/v1/offers/priceRequires X-API-Key
This step is not optional. AirShopping returns *transient* offers; the airline will not book one. OfferPrice re-confirms availability and price and mints a new offer ID, and that new ID is the only one POST /v1/orders accepts.With American Airlines the change is visible in the ID itself — the shopped offer starts AA-X… and the priced offer comes back AA-P…:| | |
|---|---|

| Sent (shopped) | AA-X2E80EC16-51FD-48AD-924B.1-1\|X2E80EC16-…-1-1 |

| Returned (priced) | AA-P2E80EC16-51FD-48AD-924B-1\|P2E80EC16-…-1-1 |

| Guaranteed until | ~20 minutes |
Booking with the *shopped* ID fails with 502 and [230000002] Invalid or Expired Offer. This is the single most common integration mistake.Routing. airline is optional — it is inferred from the offer ID prefix (everything before the first -). Send it explicitly if your offer IDs do not carry a prefix.Caching. Priced results are cached per exact set of offer IDs, so a repeat call inside the TTL does not hit the airline again.The response is a full Offer plus price_guaranteed_until. In practice AA returns the same total it shopped — a confirmed price is a confirmation, not usually a re-quote.

Request example

curl --request POST \
  --url https://api.norba.io/v1/offers/price \
  --header "X-API-Key: $NORBA_KEY" \
  --header "Content-Type: application/json" \
  --data '{ "offer_ids": ["AA-X2E80EC16-51FD-48AD-924B.1-1|X2E80EC16-51FD-48AD-924B.1-1-1"], "airline": "AA" }'

Response example

Response example
{
  "offer_id": "AA-P2E80EC16-51FD-48AD-924B-1|P2E80EC16-51FD-48AD-924B-1-1",
  "airline_offer_id": "P2E80EC16-51FD-48AD-924B-1",
  "airline": "AA",
  "source": "ndc_direct",
  "source_version": "NDC-21.3",
  "currency": "EUR",
  "total_amount": 380.62,
  "base_fare": 193,
  "taxes_fees": 187.62,
  "cabin_class": "economy",
  "baggage_included": false,
  "expires_at": "2026-08-14T09:45:23Z",
  "price_guaranteed_until": "2026-08-14T09:45:23Z",
  "passengers": [
    {
      "type": "ADT",
      "count": 1,
      "base_fare": 193,
      "taxes": 187.62,
      "total": 380.62
    }
  ],
  "slices": [
    {
      "origin": "BCN",
      "destination": "JFK",
      "stops": 0,
      "segments": [
        {
          "flight_number": "AA67",
          "aircraft": "772"
        }
      ]
    }
  ]
}

Authorization

X-API-KeystringRequired
Opaque API key issued from the Norba dashboard. Sent on every request as the X-API-Key HTTP header. Missing or invalid keys are rejected with 401 Unauthorized.

Request body

offer_idsarray<string>Required
One or more offer IDs from a shopping response. Required — an empty array returns 400 offer_ids required.
Example: ["AA-X2E80EC16-…|X2E80EC16-…-1-1"]
airlinestring
IATA code. Inferred from the first offer ID's prefix when omitted.
Example: AA

Response fields

offer_idstringRequired
The bookable offer ID. Pass this — not the shopped one — to POST /v1/orders.
price_guaranteed_untilstring (RFC 3339)Required
Deadline for creating the order at this price. Roughly 20 minutes with AA. Past it, price again.
(all Offer fields)object
The response embeds the full canonical Offer — totals, slices, segments, fare family, fare rules, passenger breakdown.

Error codes

400
offer_ids required, or unknown airline (check offer_id prefix).
404
offer no longer available at airline.
502
The airline rejected the offer — usually expired, or already priced once.
POST /v1/offers/price — Price offer | Norba API