Sandbox: real offers, real PNRs, test tickets

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 ticketed with test ticket and EMD numbers in tickets[]; a hold comes back confirmed with none. Read status and tickets[], not the HTTP code — that is the check production relies on too.
Shopping

Offer services

The à-la-carte catalogue for an offer — bags, meals, lounge, Wi-Fi, priority boarding.

GET/v1/offers/{offerID}/servicesRequires X-API-Key

Returns the airline's ServiceList for one offer, normalized into canonical Service objects.

The offer ID goes in the path and must be percent-encoded. AA offer tokens contain | and .; the API decodes the segment before routing, but your HTTP client has to encode it first. The airline query parameter is optional — it is inferred from the ID prefix.

This endpoint also accepts an order ID — with ?airline=AA added, because an order id carries no AA- prefix to infer the carrier from (400 unknown airline without it). Prefer GET /v1/orders/{orderID}/services, which is scoped to your agency and remembers what it showed.

An empty list is a normal, successful answer. AA reports "There are no available services at this time" as an error in its NDC response; the adapter recognises a wholly benign error set and translates it to [] rather than failing the call. Basic Economy and Main Cabin fares on BCN→JFK both legitimately return zero services.

Where the services get used: pass them to POST /v1/orders in the ancillaries array. Their offer references belong to the shopping context of the offer, so that is the only point at which the airline still recognises them. After booking, list and buy against the order instead — GET and POST /v1/orders/{orderID}/services — where the airline prices them against the passengers and flights it now holds.

Results are cached per offer ID.

Request example

curl --request GET \
  --url https://api.norba.io/v1/offers/{offerID}/services \
  --header "X-API-Key: $NORBA_KEY"

Response example

Response example
[
  {
    "service_id": "SRVDEF08001b075a14f",
    "type": "bag_checked",
    "name": "First checked bag",
    "description": "One piece up to 23kg",
    "price": {
      "amount": 75,
      "currency": "EUR"
    },
    "segment_refs": [
      "SGM010012275a20c"
    ],
    "pax_refs": [
      "T1"
    ]
  }
]

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.

Path parameters

offerIDstringRequired

Canonical offer ID or order ID. Percent-encode it.

Example: AA-P2E80EC16-51FD-48AD-924B-1|P2E80EC16-51FD-48AD-924B-1-1

Query parameters

airlinestring

IATA code. Inferred from the ID prefix when omitted.

Example: AA

Response fields

[].service_idstringRequired

Airline's service id — the reference you quote when buying it.

[].typestringRequired

One of bag_checked, bag_carry_on, seat, meal, lounge, fast_track, priority_boarding, insurance, upgrade, pet, sport_equipment, extra_legroom, wifi, other.

[].namestringRequired

Display name.

[].descriptionstring

Longer description when the airline supplies one.

[].priceobject

{amount, currency}.

[].segment_refsarray<string>

Segments the service applies to.

[].pax_refsarray<string>

Passengers the service applies to.

Error codes

400

unknown airline — the ID carried no recognisable prefix and no ?airline= was given.

502

The airline rejected the reference (an expired offer, typically). The body is the generic sentence; the carrier's text is in Norba's logs under your X-Request-Id.

GET /v1/offers/{offerID}/services — Offer services