Explanation of certain errors when building a flight booking engine with amadeus api - amadeus

I have been using Amadeus api to design a flight booking system. Sometimes, it goes through and the flight booking works (note that i am in sandbox mode) while some times i run into errors some of which i can't explain. I can test it now and it works and in another ten minutes i test again and an error pops up. I would love to know meaning of the frequent ones i get and how to avoid them.
here is one
"errors" : [ {
"status" : 400,
"code" : 34651,
"title" : "SEGMENT SELL FAILURE",
"detail" : "Could not sell segment 1",
"source" : {
"pointer" : "/data/flightOffers[0]/itineraries[0]/segments[0]"
}
} ]
}
here is another
"errors" : [ {
"code" : 4926,
"title" : "INVALID DATA RECEIVED",
"detail" : "No fare applicable",
"status" : 400
} ]
}```

INVALID DATA RECEIVED means that some of the data in your query is false. It can be that you sent a fare that does not match your class or the flight number is incorrect etc. This is common to all our APIs, it comes from the API backend validating your query.
SEGMENT SELL FAILURE this means that you were not able to book the seat you want in the inventory of the airline. Most of the time, it comes from the flight being full. In the test environment, you can perform many bookings without restrictions (no real payment), but the inventory is a copy of the real one, so if you book many seats, the inventory will be empty and you won't be able to book anymore. It can come from a wrong fare, or flight number as well. The good practice is to price right before booking (note that in test it can still happen as many bookings are going at the same time from other users). But with this message, it is the inventory that rejects you.

Related

Sabre BFM V4 response not showing only First Class flights as specified

`I am using Sabre BFM V4 to search for flights and I want to display only First Class flights in the response. However, the response is currently showing all flight classes, including Economy and Premium Economy.
Here is an example of the request I am making:
{
"OTA_AirLowFareSearchRQ": {
"TravelPreferences": {
"CabinPref": [
{
"Cabin": "F",
"PreferLevel": "Only"
}
]
},
...
}
}
I have confirmed that there are First Class flights available in the database, and I have specified the preferred cabin class and preference level in the request. However, I am still not getting the desired results.
Is there anything I am missing or doing wrong in my request? How can I make sure that only First Class flights are displayed in the response?
In the example request, the user is trying to specify a preference for First Class flights only using the Sabre BFM V4 API. The request sets the "Cabin" parameter to "F" to indicate First Class and the "PreferLevel" parameter to "Only" to indicate that only flights with First Class cabins should be displayed.
The user is expecting the response to only show flights with First Class cabins, but is currently getting a response that includes all flight classes.
The user is seeking assistance to determine what is causing the unexpected result and how to correct it to achieve the desired outcome of only showing First Class flights.`

REST GET mehod: Can return a list of enriched resources?

I have a doubt when I'm designing a REST API.
Consider I have a Resource "Customer" with two elements in my server, like this:
[
{
name : "Mary",
description : "An imaginary woman very tall."
},
{
name : "John",
description : "Just a guy."
}
]
And I want to make an endpoint, that will accept a GET request with a query. The query will provide a parameter with a value that will make an algorithm count how many occurrences for this text are there in all of its parameters.
So if we throw this request:
GET {baseURL}/customers?letters=ry
I should get something like
[
{
name : "Mary",
description : "An imaginary woman very tall.",
count : 3
},
{
name : "John",
description : "Just a guy.",
count : 0
}
]
Count parameter can not be included in the resource scheme as will depend on the value provided in the query, so the response objects have to be enriched.
I'm not getting a list of my resource but a modified resource.
Although it keeps the idempotent condition for GET Method, I see it escapes from the REST architecture concept (even the REST beyond CRUD).
Is it still a valid endpoint in a RESTful API? or should I create something like a new resource called "ratedCustomer"?
REST GET mehod: Can return a list of enriched resources?
TL;DR: yes.
Longer answer...
A successful GET request returns a representation of a single resource, identified by the request-target.
The fact that the information used to create the representation of the resource comes from multiple entities in your domain model, or multiple rows in your database, or from reports produced by other services... these are all implementation details. The HTTP transfer of documents over a network application doesn't care.
That also means that we can have multiple resources that include the same information in their representations. Think "pages in wikipedia" that duplicate each others' information.
Resource identifiers on the web are semantically opaque. All three of these identifiers are understood to be different resources
/A
/A?enriched
/B
We human beings looking at these identifiers might expect /A?enriched to be semantically closer to /A than /B, but the machines don't make that assumption.
It's perfectly reasonable for /A?enriched to produce representations using a different schema, or even a different content-type (as far as the HTTP application is concerned, it's perfectly reasonable that /A be an HTML document and /A?enriched be an image).
Because the machines don't care, you've got additional degrees of freedom in how you design both you resources and your resource identifiers, which you can use to enjoy additional benefits, including designing a model that's easy to implement, or easy to document, or easy to interface with, or easy to monitor, or ....
Design is what we do to get more of what we want than we would get by just doing it.

Amadeus Self-Service API currency bug. Response always in origin country currency

I originally reported this to Self-Service support in December, but I never got a response. I recently realized that, even in the production environment, selecting a currency parameter for an Inspiration or Cheapest-Date endpoint always returns the origin country's currency despite selecting another currency. (In the Low-Fare endpoint it seems to work as designed.) I tested this in both my web application and in Amadeus' own explorer tool. Here is a snip from the JSON response in the Explorer:
"meta": {
"currency": "EUR",
"links": {
"self": "https://test.api.amadeus.com/v1/shopping/flight-dates?origin=MAD&destination=MUC&departureDate=2019-04-14,2019-10-10&oneWay=false&duration=4,7&nonStop=true&currency=USD&viewBy=DATE"
},
"defaults": {
"departureDate": "2019-04-14,2019-10-10"
}
}
Notice that the meta.currency value is EUR, but the meta.links.self (the query I ran) shows a GET parameter of currency=USD. The same problem I reported in Dec.
I am posting this for suggestions about how to get some action from Amadeus (hope they read this), or a suggested workaround (obvious one is hiding Currency field from the Inspiration and Cheapest-Date form).
The currency parameter in Flight Inspiration and Cheapest Date Search, works only along with maxPrice. Prices in the response are computed in a currency determined by the origin/destination pair: they cannot be converted in a given currency.
Since it's a bit confusing, we are going to update the currency parameter naming and documentation. Point taken and sorry for the delay in the response.

In Amadeus self service APIs, is price.total inclusive of all taxes and fees?

For the Amadeus self-service rest APIs: v1/shopping/flight-offers and flight-dates, is the price.total response field inclusive of all taxes and fees?
I seem to need to add total + totalTaxes to get a price that's close to the one provided by the airline directly.
If there are developer docs that explain in more detail each response field, please do point me to them. I have been unable to find any.
In reference to these APIs:
https://developers.amadeus.com/self-service/category/203/api-doc/4/api-docs-and-example/10002
https://developers.amadeus.com/self-service/category/203/api-doc/5/api-docs-and-example/10003
and this field:
"price": {
"total": "259.91",
"totalTaxes": "185.91"
},
“total” is the total price you will have to pay, it includes the totalTaxes.
You can access the model directly on Swagger (under the Response Class (Status 200)) you have the Model button. But you are right the description of those parameters need to be added, point taken.
As highlighted in the accepted answer, the total price is the total including all taxes, personally, I was also initially confused and had to manually check with a travel agent to confirm. I would suggest Amadeus splits the description as follows
"price": {
"totalFare": "74.00",
"totalTaxes": "185.91"
"totalAmount": "259.91"
},

RESTful API - Correct behaviour when spurious/not requested parameters are passed in the request

We are developing a RESTful api that accepts query parameters in the request in the form of JSON encoded data.
We were wondering what is the correct behaviour when non requested/not expected parameters are passed along with the required ones.
For example, we may require that a PUT request on a given endpoint have to provide exactly two values respectively for the keys name and surname:
{
"name": "Jeff",
"surname": "Atwood"
}
What if a spurious key is passed too, like color in the example below?
{
"name": "Jeff",
"surname": "Atwood",
"color": "red"
}
The value for color is not expected, neither documented.
Should we ignore it or reject the request with a BAD_REQUEST 400 status error?
We can assert that the request is bad because it doesn't conform to the documentation. And probably the API user should be warned about it (She passed the value, she'll expects something for that.)
But we can assert too that the request can be accepted because, as the required parameters are all provided, it can be fulfilled.
Having used RESTful APIs from numerous vendors over the years, let me give you a "users" perspective.
A lot of times documentation is simply bad or out of date. Maybe a parameter name changed, maybe you enforce exact casing on the property names, maybe you have used the wrong font in your documentation and have an I which looks exactly like an l - yes, those are different letters.
Do not ignore it. Instead, send an error message back stating the property name with an easy to understand message. For example "Unknown property name: color".
This one little thing will go a long ways towards limiting support requests around consumption of your API.
If you simply ignore the parameters then a dev might think that valid values are being passed in while cussing your API because obviously the API is not working right.
If you throw a generic error message then you'll have dev's pulling their hair out trying to figure out what's going on and flooding your forum, this site or your phone will calls asking why your servers don't work. (I recently went through this problem with a vendor that just didn't understand that a 404 message was not a valid response to an incorrect parameter and that the documentation should reflect the actual parameter names used...)
Now, by the same token I would expect you to also give a good error message when a required parameter is missing. For example "Required property: Name is missing".
Essentially you want to be as helpful as possible so the consumers of your API can be as self sufficient as possible. As you can tell I wholeheartedly disagree with a "gracious" vs "stern" breakdown. The more "gracious" you are, the more likely the consumers of your API are going to run into issues where they think they are doing the right thing but are getting unexpected behaviors out of your API. You can't think of all possible ways people are going to screw up so enforcing a strict adherence with relevant error messages will help out tremendously.
If you do an API design you can follow two path: "stern" or "gracious".
Stern means: If you do anything I didn't expect I will be mad at you.
Gracious means: If I know what you want and can fulfil it I will do it.
REST allows for a wonderful gracious API design and I would try to follow this path as long as possible and expect the same of my clients. If my API evolves I might have to add additional parameters in my responses that are only relevant for specific clients. If my clients are gracious to me they will be able to handle this.
Having said that I want to add that there is a place for stern API design. If you are designing in an sensitive domain (e.g. cash transactions) and you don't want to leave room for any misunderstanding between the client and server. Imagine the following POST request (valid for your /account/{no}/transaction/ API):
{ amount: "-100", currency : "USD" }
What would you do with the following (invalid API request)?
{ amount: "100", currency : "USD", type : "withdrawal" }
If you just ignore the "type" attribute, you will deposit 100 USD instead of withdrawing them. In such a domain I would follow a stern approach and show no grace whatsoever.
Be gracious if you can, be stern if you must.
Update:
I totally agree with #Chris Lively's answer that the user should be informed. I disagree that it should always be an error case even the message is non-ambiguous for the referenced resource. Doing it otherwise will hinder reuse of resource representations and require repackaging of semantically identical information.
It depends on your documentation.. how strict you want to be .. But commonly speaking, Just ignore it. Most other servers also ignore request parameters it didn't understand.
Example taken from my previous post
Extra Query parameters in the REST API Url
"""Google ignore my two extra parameters here https://www.google.com/#q=search+for+something&invalid=param&more=stuff"""
Imagine I have the following JSON schema:
{
"frequency": "YEARLY",
"date": 23,
"month": "MAY",
}
The frequency attribute accepts "WEEKLY", "MONTHLY" and "YEARLY" value.
The expected payload for "WEEKLY" frequency value is:
{
"frequency": "WEEKLY",
"day": "MONDAY",
}
And the expected payload for "MONTHLY" frequency value is:
{
"frequency": "MONTHLY",
"date": 23,
}
Give the above JSON schema, typically I will have need a POJO containing frequency, day, date, and month fields for deserialization.
If the received payload is:
{
"frequency": "MONTHLY",
"day": "MONDAY",
"date": 23,
"year": 2018
}
I will throw an error on "day" attribute because I will never know the intention of the sender:
frequency: "WEEKLY" and day: "MONDAY" (incorrect frequency value entered), or
frequency: "MONTHLY" and date: 23
For the "year" attribute, I don't really have choice.
Even if I wish to throw an error for that attribute, I may not be able to.
It's ignored by the JSON serialization/deserialization library as my POJO has no such attribute. And this is the behavior of GSON and it makes sense given the design decision.
Navigating the Json tree or the target Type Tree while deserializing
When you are deserializing a Json string into an object of desired type, you can either navigate the tree of the input, or the type tree of the desired type. Gson uses the latter approach of navigating the type of the target object. This keeps you in tight control of instantiating only the type of objects that you are expecting (essentially validating the input against the expected "schema"). By doing this, you also ignore any extra fields that the Json input has but were not expected.
As part of Gson, we wrote a general purpose ObjectNavigator that can take any object and navigate through its fields calling a visitor of your choice.
Extracted from GSON Design Document
Just ignore them.
Do not give the user any chance to reverse engineer your RESTful API through your error messages.
Give the developers the neatest, clearest, most comprehensive documentation and parse only parameters your API need and support.
I will suggest that you ignore the extra parameters. Reusing API is a game changer in the integration world. What if the same API can be used by other integration but with slightly extra parameters?
Application A expecting:
{
"name": "Jeff",
"surname": "Atwood"
}
Application B expecting:
{
"name": "Jeff",
"surname": "Atwood",
"color": "red"
}
Simple get application application A to ignore "color" will do the job rather to have 2 different API to handle that.