Midlandgeeks - Cloud Solutions for SME’s    

The Amadeus Flight Booking Journey - API Calls

The Amadeus Flight Booking Journey - API Calls

 

The Amadeus Flight Booking service consists of three separate API calls.  The first of these is the Flight Offers Search

The following code snippet represents the Flight Offers Search called from a python environment

# Install the Python library from https://pypi.org/project/amadeus

from amadeus import Client, ResponseError

 

amadeus = Client(

    client_id='your_client_id',

    client_secret='your_client_secret'

)

try:

    '''

    Find the cheapest flights from BHX to SVQ

    '''

    response = amadeus.shopping.flight_offers_search.get(

        currencyCode='GBP',

        originLocationCode='BHX',

        destinationLocationCode='SVQ',

        departureDate='2025-06-21',

        adults=1,

        children=0,

        infants=0,

        max=1)

    print(response.data)

except ResponseError as error:

    raise error

From a correctly invoked python environment - call flight_offers_search.py

(amadeus) [ec2-user@ip-172-31-12-162 amadeus-flight-booking-django]$ python api/flight_offers_search.py 

The service retures -

{
  "type": "flight-offer",
  "id": "1",
  "source": "GDS",
  "instantTicketingRequired": false,
  "nonHomogeneous": false,
  "oneWay": false,
  "isUpsellOffer": false,
  "lastTicketingDate": "2025-05-22",
  "lastTicketingDateTime": "2025-05-22",
  "numberOfBookableSeats": 9,
  "itineraries": [
    {
      "duration": "PT15H25M",
      "segments": [
        {
          "departure": {"iataCode": "BHX", "at": "2025-06-21T17:35:00"},
          "arrival": {"iataCode": "AMS", "at": "2025-06-21T19:50:00"},
          "carrierCode": "KL",
          "number": "1048",
          "aircraft": {"code": "73H"},
          "operating": {"carrierCode": "KL"},
          "duration": "PT1H15M",
          "id": "1",
          "numberOfStops": 0,
          "blacklistedInEU": false
        },
        {
          "departure": {"iataCode": "AMS", "at": "2025-06-22T07:05:00"},
          "arrival": {"iataCode": "SVQ", "at": "2025-06-22T10:00:00"},
          "carrierCode": "KL",
          "number": "2544",
          "aircraft": {"code": "32Q"},
          "operating": {"carrierCode": "HV"},
          "duration": "PT2H55M",
          "id": "2",
          "numberOfStops": 0,
          "blacklistedInEU": false
        }
      ]
    }
  ],
  "price": {
    "currency": "GBP",
    "total": "166.17",
    "base": "86.00",
    "fees": [
      {"amount": "0.00", "type": "SUPPLIER" },
      {"amount": "0.00", "type": "TICKETING"}
    ],
    "grandTotal": "166.17"
  },
  "pricingOptions": {
    "fareType": ["PUBLISHED"],
    "includedCheckedBagsOnly": true
  },
  "validatingAirlineCodes": ["AF"],
  "travelerPricings": [
    {
      "travelerId": "1",
      "fareOption": "STANDARD",
      "travelerType": "ADULT",
      "price": {"currency": "GBP", "total": "166.17", "base": "86.00"},
      "fareDetailsBySegment": [
        {
          "segmentId": "1",
          "cabin": "ECONOMY",
          "fareBasis": "GYQFBBSA",
          "brandedFare": "STANDARD",
          "brandedFareLabel": "ECONOMY STANDARD",
          "class": "G",
          "includedCheckedBags": {"quantity": 1},
          "includedCabinBags": {"quantity": 1},
          "amenities": [
            {
              "description": "SNACK",
              "isChargeable": false,
              "amenityType": "MEAL",
              "amenityProvider": {"name": "BrandedFare"}
            },
            {
              "description": "BEVERAGE",
              "isChargeable": false,
              "amenityType": "MEAL",
              "amenityProvider": {"name": "BrandedFare"}
            },
            {
              "description": "SEAT SELECTION",
              "isChargeable": true,
              "amenityType": "BRANDED_FARES",
              "amenityProvider": {"name": "BrandedFare"}
            },
            {
              "description": "MILEAGE ACCRUAL",
              "isChargeable": false,
              "amenityType": "BRANDED_FARES",
              "amenityProvider": {"name": "BrandedFare"}
            },
            {
              "description": "UPGRADE ELIGIBILITY",
              "isChargeable": true,
              "amenityType": "BRANDED_FARES",
              "amenityProvider": {"name": "BrandedFare"}
            },
            {
              "description": "CHANGEABLE TICKET",
              "isChargeable": true,
              "amenityType": "BRANDED_FARES",
              "amenityProvider": {"name": "BrandedFare"}
            }
          ]
        },
        {
          "segmentId": "2",
          "cabin": "ECONOMY",
          "fareBasis": "GYQFBBSA",
          "brandedFare": "STANDARD",
          "brandedFareLabel": "ECONOMY STANDARD",
          "class": "G",
          "includedCheckedBags": {"quantity": 1},
          "amenities": [
            {
              "description": "SNACK",
              "isChargeable": false,
              "amenityType": "MEAL",
              "amenityProvider": {"name": "BrandedFare"}
            },
            {
              "description": "BEVERAGE",
              "isChargeable": false,
              "amenityType": "MEAL",
              "amenityProvider": {"name": "BrandedFare"}
            },
            {
              "description": "SEAT SELECTION",
              "isChargeable": true,
              "amenityType": "BRANDED_FARES",
              "amenityProvider": {"name": "BrandedFare"}
            },
            {
              "description": "MILEAGE ACCRUAL",
              "isChargeable": false,
              "amenityType": "BRANDED_FARES",
              "amenityProvider": {"name": "BrandedFare"}
            },
            {
              "description": "UPGRADE ELIGIBILITY",
              "isChargeable": true,
              "amenityType": "BRANDED_FARES",
              "amenityProvider": {"name": "BrandedFare"}
            },
            {
              "description": "CHANGEABLE TICKET",
              "isChargeable": true,
              "amenityType": "BRANDED_FARES",
              "amenityProvider": {"name": "BrandedFare"}
            }
          ]
        }
      ]
    }
  ]
}
 

Amadeus Flight API xml cleansing

 

The flight search xml returned from an API call seems to require cleansing in order to use standard xml manipulation on the returned data.  In the crudest form the following will clean the xml in order for commands like jq to run gracefully -

 

python api/flight_offers_search.py | sed  s/\'\/\"\/g | sed s/False/\"False\"/g | sed s/True/\"True\"/g | jq .

Effectively this series of sed manipulation 1.  Changes  the data for the xml parameter from single quote to double-quote 2. Inserts double-quotes around parameters returning a False response 3.  Inserts a double-quote around parameters returning a True response.  This is ultimately piped to jq to prettify the xml.

The successful generation of flight offers marks the end of the first api call.  The second api call, flight offers price is required to confirm the selected flight is still valid.  This call is typically invoked on booking.

(amadeus) [ec2-user@ip-172-31-12-162 amadeus-flight-booking-django]$ python api/code-example-price.py

The call returns the proposed booking details with any caveats to the original request if any.

{
  "warnings": [
    {
      "code": 0,
      "title": "PricingOrFareBasisDiscrepancyWarning",
      "detail": "Actual price and/or fare basis for some passengers is different from requested ones",
      "status": 200
    }
  ],
  "data": {
    "type": "flight-offers-pricing",
    "flightOffers": [
      {
        "type": "flight-offer",
        "id": "1",
        "source": "GDS",
        "instantTicketingRequired": false,
        "nonHomogeneous": false,
        "paymentCardRequired": false,
        "lastTicketingDate": "2025-05-27",
        "itineraries": [
          {
            "segments": [
              {
                "departure": {
                  "iataCode": "BHX",
                  "at": "2025-06-21T17:35:00"
                },
                "arrival": {
                  "iataCode": "AMS",
                  "at": "2025-06-21T19:50:00"
                },
                "carrierCode": "KL",
                "number": "1048",
                "aircraft": {
                  "code": "73H"
                },
                "operating": {
                  "carrierCode": "KL"
                },
                "duration": "PT1H15M",
                "id": "17",
                "numberOfStops": 0,
                "co2Emissions": [
                  {
                    "weight": 64,
                    "weightUnit": "KG",
                    "cabin": "ECONOMY"
                  }
                ]
              },
              {
                "departure": {
                  "iataCode": "AMS",
                  "at": "2025-06-22T07:05:00"
                },
                "arrival": {
                  "iataCode": "SVQ",
                  "at": "2025-06-22T10:00:00"
                },
                "carrierCode": "KL",
                "number": "2544",
                "aircraft": {
                  "code": "32Q"
                },
                "operating": {
                  "carrierCode": "HV"
                },
                "duration": "PT2H55M",
                "id": "18",
                "numberOfStops": 0,
                "co2Emissions": [
                  {
                    "weight": 117,
                    "weightUnit": "KG",
                    "cabin": "ECONOMY"
                  }
                ]
              }
            ]
          }
        ],
        "price": {
          "currency": "GBP",
          "total": "177.17",
          "base": "97.00",
          "fees": [
            {
              "amount": "0.00",
              "type": "SUPPLIER"
            },
            {
              "amount": "0.00",
              "type": "TICKETING"
            },
            {
              "amount": "0.00",
              "type": "FORM_OF_PAYMENT"
            }
          ],
          "grandTotal": "177.17",
          "billingCurrency": "GBP"
        },
        "pricingOptions": {
          "fareType": [
            "PUBLISHED"
          ],
          "includedCheckedBagsOnly": true
        },
        "validatingAirlineCodes": [
          "AF"
        ],
        "travelerPricings": [
          {
            "travelerId": "1",
            "fareOption": "STANDARD",
            "travelerType": "ADULT",
            "price": {
              "currency": "GBP",
              "total": "177.17",
              "base": "97.00",
              "taxes": [
                {
                  "amount": "10.50",
                  "code": "CJ"
                },
                {
                  "amount": "20.00",
                  "code": "YQ"
                },
                {
                  "amount": "1.25",
                  "code": "YR"
                },
                {
                  "amount": "13.00",
                  "code": "GB"
                },
                {
                  "amount": "12.10",
                  "code": "RN"
                },
                {
                  "amount": "23.32",
                  "code": "UB"
                }
              ],
              "refundableTaxes": "58.92"
            },
            "fareDetailsBySegment": [
              {
                "segmentId": "17",
                "cabin": "ECONOMY",
                "fareBasis": "XYQDBBSA",
                "brandedFare": "STANDARD",
                "class": "X",
                "includedCheckedBags": {
                  "quantity": 1
                }
              },
              {
                "segmentId": "18",
                "cabin": "ECONOMY",
                "fareBasis": "XYQDBBSA",
                "brandedFare": "STANDARD",
                "class": "X",
                "includedCheckedBags": {
                  "quantity": 1
                }
              }
            ]
          }
        ]
      }
    ],
    "bookingRequirements": {
      "emailAddressRequired": true,
      "mobilePhoneNumberRequired": true
    }
  },
  "dictionaries": {
    "locations": {
      "BHX": {
        "cityCode": "BHX",
        "countryCode": "GB"
      },
      "AMS": {
        "cityCode": "AMS",
        "countryCode": "NL"
      },
      "SVQ": {
        "cityCode": "SVQ",
        "countryCode": "ES"
      }
    }
  }
Caveats

.This blog is mostly about helping small and medium sized businesses use technology. Size necessarily dictates different priorities but the ability to apply the tools available to differentiate your online presence should not be a constraint to growing your business. Helping you bring your ideas to fruition is what we’re about. Perhaps developing ways which allow you to better connect with your customers by implementing a new service platform or simply a rejuvenation of your website...

Know more!