In the sandbox these endpoints work against real carrier test inventory: a search returns real offers and you can create a real booking with a carrier PNR. Two things are worth knowing before you build against them.
- Sandbox orders are test reservations. Nobody flies on them, and they raise no fee. Cancel what you create; anything left over expires on its own payment time limit.
- Sandbox tickets are test documents. A paid order comes back
ticketedwith test ticket and EMD numbers intickets[]; a hold comes backconfirmedwith none. Readstatusandtickets[], not the HTTP code — that is the check production relies on too.
Price offer
Confirm the price with the airline and mint the bookable offer ID. Mandatory before booking.
/v1/offers/priceRequires X-API-KeyThis 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 422 airline_refused before the airline is called (the body is the generic sentence, so check the prefix yourself). This is the single most common integration mistake. An offer the carrier will no longer price answers 422 offer_expired when the connector can tell, 502 otherwise.
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
{
"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"
}
]
}
]
}Request body
offer_idsarray<string>RequiredOne or more offer IDs from a shopping response. Required — an empty array returns 400 offer_ids required.
["AA-X2E80EC16-…|X2E80EC16-…-1-1"]airlinestringIATA code. Inferred from the first offer ID's prefix when omitted.
AAResponse fields
offer_idstringRequiredThe bookable offer ID. Pass this — not the shopped one — to POST /v1/orders.
price_guaranteed_untilstring (RFC 3339)RequiredDeadline for creating the order at this price. Roughly 20 minutes with AA. Past it, price again.
(all Offer fields)objectThe response embeds the full canonical Offer — totals, slices, segments, fare family, fare rules, passenger breakdown.
Error codes
400offer_ids required, or unknown airline (check offer_id prefix).
404offer no longer available at airline.
422offer_expired — the carrier will no longer price this offer; search and price again.
502The airline rejected the offer and the connector could not say why — usually expired, or already priced once. The body is the generic sentence; the carrier's text is in Norba's logs under your X-Request-Id.