Reputation: 37
For reference, I'm a novice trying to learn Python and working with British Airway's Flight Offer Basic API, who's documentation can be found here:
https://developer.ba.com/docs/api/Flight_Offer_Basic
Using the Requests library documentation from docs.python-requests, I'm trying to build a matching API call that actually works, but I'm getting a 403 when not including my API key and just the necessary parameters for the query (which makes sense), but a 400 when I include both the parameters and the API key...which doesn't make sense, except for when I view what my API calls look like and what the the successful example they provide looks like:
(NOTE: HTTP: removed as I cannot post more than two links at the moment)
Mine:
//api.ba.com/rest-v1/v1/flightOfferBasic?range=monthLow&departureCity=LON&arrivalCity=NYC&cabin=economy&journeyType=roundTrip
Theirs:
//api.ba.com/rest-v1/v1/flightOfferBasic;departureCity=LON;arrivalCity=NYC;cabin=economy;journeyType=roundTrip;range=monthLow.json
EDITED: 6/6/15 at 12:20PM PST; I mucked up the code in some testing and didn't realize I hadn't reverted it back, specifically the 'journeyType'.
Here's my code:
import requests
import pprint
parameters = { 'departureCity': 'LON',
'arrivalCity': 'NYC',
'cabin': 'economy',
'journeyType': 'roundTrip',
'range': 'monthLow'
}
endpoint = 'https://api.ba.com/rest-v1/v1/flightOfferBasic'
headers = {'client-key': 'h6z...'}
response = requests.get(endpoint, params = parameters, headers = headers)
data = response.json
pprint.pprint(data)
I noticed that I have an "&" joining each parameter in the call, and the successful call has a ";" joining each parameter in the call, which seems to be why I get a 400 "Sent when the consumer sends a malformed request to the service. The actual error message is returned in the response body".
When I check the body of the response, I'm told this:
{"Errors":{"Error":"invalid range"}}
But I've double- and triple-checked that that's the proper key value and string. When I remove the range to test, I'm told "invalid cabin". When I remove the cabin, I'm still told "invalid cabin". But I've double- and triple-checked that that's the proper key value and string for the cabin.
The successful call also has ".json" at the end, but I believe that the "response.json" call should convert the returned data into a JSON object...right? Another odd thing is that, then passing in the "format" parameter as ".json" as the documentation suggests:
parameters = { 'departureCity': 'LON',
'arrivalCity': 'NYC',
'cabin': 'economy',
'journeyType': 'roundTrip',
'range': 'monthLow',
'format': '.json'
}
I get this URL for the API call:
//api.ba.com/rest-v1/v1/flightOfferBasic?format=.json&arrivalCity=NYC&range=monthLow&journeyType=roundTrip&departureCity=LON&cabin=economy
It's injected as the first parameter, when it should be the last, and when it's the last parameter in my "parameters" dictionary as well.
Any idea where I'm going wrong?
Upvotes: 2
Views: 2398
Reputation: 599946
Argh. That is a horribly designed API.
The problem, as you noticed, is that they want parameters separated by semicolons. That means they are not part of the querystring at all, which is what requests does when you give it a params
dict, but part of the actual URL path.
You'll need to build that up manually, eg by string interpolation:
parameters = { 'departureCity': 'LON',
'arrivalCity': 'NYC',
'cabin': 'economy',
'journeyType': 'oneWay',
'range': 'monthLow'
}
path = ';'.join('{}={}'.format(k, v) for k, v in parameters.items())
endpoint = 'https://api.ba.com/rest-v1/v1/flightOfferBasic'
url = '{};{}'.format(endpoint, path)
response = requests.get(url, headers=headers)
Upvotes: 2