Search code examples
rcurlhttramadeus

Call Amadeus flight-offers-pricing API from R?


Update: Here is code that shows how to get an access token. I also use the test api here which is free (no credit card required).

The first api call to test.api.amadeus.com/v2/shopping/flight-offers is shown.

It is the second api call to test.api.amadeus.com/v1/shopping/flight-offers/pricing api that I don't know how to format.

My question remains, what is the correct way to call the second API using R?

R Script

library("tidyverse")
library("httr")
library("rjson")

amadeus_api_key_prod <- Sys.getenv("AMADEUS_API_KEY") 
amadeus_api_secret_prod <- Sys.getenv("AMADEUS_SECRET") 

# Initialize variables
tmp_origin <- NULL
tmp_dest <- NULL
tmp_avg_total_fare <- NULL

# Get Token
response <- POST("https://test.api.amadeus.com/v1/security/oauth2/token",
                 add_headers("Content-Type" = "application/x-www-form-urlencoded"),
                 body = list(
                   "grant_type"     = "client_credentials",
                   "client_id"      = amadeus_api_key_prod,
                   "client_secret"  = amadeus_api_secret_prod),
                 encode = "form")
response
rsp_content <- content(response, as = "parsed", type = "application/json")
access_token <- paste0("Bearer ", rsp_content$access_token)

origin <- "JFK"
dest <- "LHR"
dep_date <- "2021-12-01"
return_date <- "2021-12-18"
max_num_flights <- 1

url <- paste0("https://test.api.amadeus.com/v2/shopping/flight-offers?originLocationCode=", 
              origin, 
              "&destinationLocationCode=",
              dest,
              "&departureDate=",
              dep_date,
              "&returnDate=",
              return_date,
              "&max=",
              max_num_flights,
              "&adults=1&nonStop=false&travelClass=ECONOMY&max=1&currencyCode=CAD")

# Get flight info
response <- GET(url,
                add_headers("Content-Type" = "application/x-www-form-urlencoded",
                            "Authorization" = access_token),
                encode = "form")

response
rsp_content <- content(response, as = "parsed", type = "application/json")
rsp_content

# Get current, more detailed flight info
# This is the part I do not know how to do
url2 <- "https://test.api.amadeus.com/v1/shopping/flight-offers/pricing"

flt_info <- toJSON(rsp_content[["data"]])

response2 <- GET(url2,
                 add_headers("Authorization" = access_token),
                 body = list(
                   "priceFlightOffersBody" = flt_info
                 ),
                 encode = "form")

response2
rsp_content2 <- content(response2, as = "parsed", type = "application/json")
rsp_content2

Original Question

I am using the Amadeus flight info api to retrieve prices for flights. My understanding is that to get complete price info requires two steps.

  1. Call to https://api.amadeus.com/v2/shopping/flight-offers api
  2. Call to https://api.amadeus.com/v1/shopping/flight-offers/pricing api

I can successfully perform the first api call with origin, destination, dates, etc. The second call, confirms the pricing is still available and has a more detailed breakdown of the fare than does the first api call. It is this detailed breakdown that I am most interested in.

I am having trouble understanding what info that gets returned from the first api call needs to be passed to the second api call and in what format.

Below, I have included the data structure that gets returned from the first api call and my failed attempt to call the second api.

What is the correct way to call the second API using R?

Links to what I believe is the relevant documentation:

# Data structure returned from call to https://api.amadeus.com/v2/shopping/flight-offers
# For YYZ to YOW return, Dec 1-18 economy
rsp_content <- list(meta = list(count = 1L, links = list(self = "https://api.amadeus.com/v2/shopping/flight-offers?originLocationCode=YYZ&destinationLocationCode=YOW&departureDate=2021-12-01&returnDate=2021-12-18&max=1&adults=1&nonStop=false&travelClass=ECONOMY&max=1&currencyCode=CAD")), 
                    data = list(list(type = "flight-offer", id = "1", source = "GDS", 
                                     instantTicketingRequired = FALSE, nonHomogeneous = FALSE, 
                                     oneWay = FALSE, lastTicketingDate = "2021-08-07", numberOfBookableSeats = 7L, 
                                     itineraries = list(list(duration = "PT1H10M", segments = list(
                                       list(departure = list(iataCode = "YYZ", terminal = "3", 
                                                             at = "2021-12-01T11:00:00"), arrival = list(iataCode = "YOW", 
                                                                                                         at = "2021-12-01T12:10:00"), carrierCode = "WS", 
                                            number = "3462", aircraft = list(code = "DH4"), 
                                            duration = "PT1H10M", id = "1", numberOfStops = 0L, 
                                            blacklistedInEU = FALSE))), list(duration = "PT1H21M", 
                                                                             segments = list(list(departure = list(iataCode = "YOW", 
                                                                                                                   at = "2021-12-18T10:45:00"), arrival = list(iataCode = "YYZ", 
                                                                                                                                                               terminal = "3", at = "2021-12-18T12:06:00"), 
                                                                                                  carrierCode = "WS", number = "3463", aircraft = list(
                                                                                                    code = "DH4"), duration = "PT1H21M", id = "2", 
                                                                                                  numberOfStops = 0L, blacklistedInEU = FALSE)))), 
                                     price = list(currency = "CAD", total = "232.78", base = "125.00", 
                                                  fees = list(list(amount = "0.00", type = "SUPPLIER"), 
                                                              list(amount = "0.00", type = "TICKETING")), grandTotal = "232.78"), 
                                     pricingOptions = list(fareType = list("PUBLISHED"), includedCheckedBagsOnly = FALSE), 
                                     validatingAirlineCodes = list("WS"), travelerPricings = list(
                                       list(travelerId = "1", fareOption = "STANDARD", travelerType = "ADULT", 
                                            price = list(currency = "CAD", total = "232.78", 
                                                         base = "125.00"), fareDetailsBySegment = list(
                                                           list(segmentId = "1", cabin = "ECONOMY", fareBasis = "LAVD0TBJ", 
                                                                brandedFare = "BASIC", class = "E", includedCheckedBags = list(
                                                                  quantity = 0L)), list(segmentId = "2", 
                                                                                        cabin = "ECONOMY", fareBasis = "LAVD0ZBI", 
                                                                                        brandedFare = "BASIC", class = "E", includedCheckedBags = list(
                                                                                          quantity = 0L))))))), dictionaries = list(
                                                                                            locations = list(YOW = list(cityCode = "YOW", countryCode = "CA"), 
                                                                                                             YYZ = list(cityCode = "YTO", countryCode = "CA")), 
                                                                                            aircraft = list(DH4 = "DE HAVILLAND DHC-8 400 SERIES"), 
                                                                                            currencies = list(CAD = "CANADIAN DOLLAR"), carriers = list(
                                                                                              WS = "WESTJET")))


# Get full pricing info
url2 <- "https://api.amadeus.com/v1/shopping/flight-offers/pricing"

# Get pricing info
response2 <- GET(url2,
                add_headers("Authorization" = access_token),
                body = list(
                  "priceFlightOffersBody" = rsp_content[["data"]][[1]]
                ),
                encode = "form")

response2
rsp_content2 <- content(response2, as = "parsed", type = "application/json")
rsp_content2

Solution

  • It seems to work with the following, for the second request.

    Changes :

    • Use POST, not GET
    • While the documentation names the body priceFlightOffersBody, it should actually be just the data part, no need to encapsulate in another list.
    • The data part is not exactly the same as the result of the first request.
    • Pass the data part as an R list and use POST argument encode = "json".
    url2 <- "https://test.api.amadeus.com/v1/shopping/flight-offers/pricing"
    
    flt_info <- list(data = list(type = "flight-offers-pricing",
                                 flightOffers = rsp_content$data))
    response2 <- POST(url2,
                      add_headers(Authorization = access_token),
                      body = flt_info,
                      encode = "json")
    
    rsp_content2 <- content(response2, as = "parsed", type = "application/json")
    rsp_content2