I keep getting numberOfstops in the flightOffer API response as 0 even when there is a stop - amadeus

I am new to the Amadeus API and generally the flight business as a whole but I have set up a dev account with Amadeus and I am on a test Plan at the moment. I made a call to the flightOffers API thus;
await Amadeus.shopping.flightOffersSearch.get({myRequestPayload})
I got a successful response with 2 offers. However, my confusion is around the field numberOfStops which is 0 in the response. Please see the segments below as copied from the response I got;
"segments": [
{
"departure": {
"iataCode": "SYD",
"terminal": "1",
"at": "2022-11-01T11:35:00"
},
"arrival": {
"iataCode": "MNL",
"terminal": "2",
"at": "2022-11-01T16:50:00"
},
"carrierCode": "PR",
"number": "212",
"aircraft": {
"code": "333"
},
"operating": {
"carrierCode": "PR"
},
"duration": "PT8H15M",
"id": "1",
"numberOfStops": 0,
"blacklistedInEU": false
},
{
"departure": {
"iataCode": "MNL",
"terminal": "1",
"at": "2022-11-01T19:20:00"
},
"arrival": {
"iataCode": "BKK",
"at": "2022-11-01T21:50:00"
},
"carrierCode": "PR",
"number": "732",
"aircraft": {
"code": "321"
},
"operating": {
"carrierCode": "PR"
},
"duration": "PT3H30M",
"id": "2",
"numberOfStops": 0,
"blacklistedInEU": false
}
]
From my understanding from what I have read recently about Direct, NonStops flights, this flight is definitely not NonStop since there is a stop at MNL.
Hence I think the numberOfStops should be say 2 since:
It is a round trip
For each trip, it stops at MNL
I am just guessing this Number based on what is apparent to me. Please correct me If I am wrong.
I need to understand why numberOfStops = 0 and not > 0.
Is there a way to determine the numberOfStops without relying on the value returned?
Thanks and I anticipate any help soonest.

numberOfStops is the number of stops planned on the segment for technical or operation purpose i.e. refueling. The API will rarely return with a value but when it does it means that a segment is flown with the same plane. This represents a scheduled stop for technical/operational purposes like for example to refuel. You can check the description of the parameter in the specification file.
The API does not directly return the number of flight connections. This will need to be checked by looking at the segment size. If a segment has 2 items it means it has 2 flights. In the case of a round trip, then itineraries[0] contains the segments of the way to go back, and itineraries[1] contains the segments (flights) of the way back.

Related

Adobe Analytics - how to get report API 2.0 to get multi-level breakdown data using Java

I need help in getting adobe-analytics data when multiple IDs are passed for multi-level breakdown using API 2.0.
I am getting first level data for V124 ----
"metricContainer": {
"metrics": [
{
"columnId": "0",
"id": "metrics/event113",
"sort": "desc"
}
]
},
"dimension": "variables/evar124",
but i want to use IDs returned in above call response to in second level breakdown of v124 to get v125 as---
"metricContainer": {
"metrics": [
{
"columnId": "0",
"id": "metrics/event113",
"sort": "desc",
"filters": [
"0"
]
}
],
"metricFilters": [
{
"id": "0",
"type": "breakdown",
"dimension": "variables/evar124",
"itemId": "2629267831"
},
{
"id": "1",
"type": "breakdown",
"dimension": "variables/evar124",
"itemId": "2629267832"
}
]
},
"dimension": "variables/evar125",
This always returns data only for 2629267831 ID and not 2629267832.
I want to get data for thousands of IDs (returned from first API call) in a single API call. What am i doing wrong?

How to set the maxFlightTime in a flight offers search with the Amadeus API?

I am making a POST to the Amadeus API for flight offers.
I am trying to set the maxFlightTime parameter.
The API documentation says:
maxFlightTime number example: 200 This option allows to modify the
value for the Elapsed Flying Time (EFT) masterPricer option
https://developers.amadeus.com/self-service/category/air/api-doc/flight-offers-search/api-reference
My question is:
What does this parameter expect? The documentation says a number and provides 200 as an example.
What does the number represent? Is it minutes, hours, or something different?
maxFlightTime is a bit complex to use. The number is a percentage expressing how much longer the flight offers you want to find can be compared to the shortest flight that exists for these search criteria.
Let's take an example:
We are looking for a flight from MAD to SFO (and we are returning only 1 offer for the sake of the example) using the POST endpoint of Flight Offers Search:
JSON Body:
{
"currencyCode": "EUR",
"originDestinations": [
{
"id": "1",
"originLocationCode": "MAD",
"destinationLocationCode": "SFO",
"departureDateTimeRange": {
"date": "2021-05-01",
"time": "10:00:00"
}
}
],
"travelers": [
{
"id": "1",
"travelerType": "ADULT",
"fareOptions": [
"STANDARD"
]
}
],
"sources": [
"GDS"
],
"searchCriteria": {
"maxFlightOffers": 1,
"flightFilters": {
"cabinRestrictions": [
{
"cabin": "ECONOMY",
"coverage": "MOST_SEGMENTS",
"originDestinationIds": [
"1"
]
}
]
}
}
}
If you check the JSON response you will see that the offer is MAD to IST (duration PT4H15M so 4h15) and IST to SFO (duration PT13H20M so 13h20M) so in total duration of 17h35. Note that this API always returns the cheapest flight offers for the given criteria.
If now we want to do the same request adding maxFlightTime but we don't want to have such a long trip, we want to have a maximum total duration of 110% longer than the shortest flight available.
We can use this JSON body
{
"currencyCode": "EUR",
"originDestinations": [
{
"id": "1",
"originLocationCode": "MAD",
"destinationLocationCode": "SFO",
"departureDateTimeRange": {
"date": "2021-05-01",
"time": "10:00:00"
}
}
],
"travelers": [
{
"id": "1",
"travelerType": "ADULT",
"fareOptions": [
"STANDARD"
]
}
],
"sources": [
"GDS"
],
"searchCriteria": {
"maxFlightOffers": 1,
"flightFilters": {
"maxFlightTime": 110,
"cabinRestrictions": [
{
"cabin": "ECONOMY",
"coverage": "MOST_SEGMENTS",
"originDestinationIds": [
"1"
]
}
]
}
}
}
This is the response you will get:
MAD to DFW for a duration of PT10H35M (10h35) and then DAL (another Dallas Airport?) to SFO for a duration of
PT4H4M (4h04) so a total duration of 14h39.
This is why maxFlightTime can only be between 100 and 999.
The API specification is not very clear for this parameter, we will update it very soon.

Strange prices from Amadeus

I am checking the Amadeus about flight tickets and a little confused about the prices that I get. I expected to see prices from Amadeus closer to airline website prices or a little cheaper. But, I see that prices are incredibly high. For example, I made the following request:
https://api.amadeus.com/v2/shopping/flight-offers?originLocationCode=SGN&destinationLocationCode=DAD&departureDate=2020-05-29&adults=1&nonStop=true&currencyCode=VND
Flight at Amadeus Price In USD Airline price in USD
11:45 ~70.41 ~38.72
13:50 ~70.41 ~34.43
18:00 ~70.41 ~42.93
Prices are higher significantly. Moreover, prices from Amadeus are the same for a lot of flights for the same air company.
Do I do something wrong or I skipped something?
PS: Response for first flight:
{
"type": "flight-offer",
"id": "1",
"source": "GDS",
"instantTicketingRequired": false,
"nonHomogeneous": false,
"oneWay": false,
"lastTicketingDate": "2020-05-29",
"numberOfBookableSeats": 4,
"itineraries": [{
"duration": "PT1H20M",
"segments": [{
"departure": {
"iataCode": "SGN",
"terminal": "1",
"at": "2020-05-29T11:15:00"
},
"arrival": {
"iataCode": "DAD",
"terminal": "1",
"at": "2020-05-29T12:35:00"
},
"carrierCode": "VJ",
"number": "628",
"aircraft": {
"code": "321"
},
"operating": {
"carrierCode": "VJ"
},
"duration": "PT1H20M",
"id": "9",
"numberOfStops": 0,
"blacklistedInEU": false
}]
}],
"price": {
"currency": "VND",
"total": "1640000.00",
"base": "1381000.00",
"fees": [{
"amount": "0.00",
"type": "SUPPLIER"
},
{
"amount": "0.00",
"type": "TICKETING"
}
],
"grandTotal": "1640000.00"
},
"pricingOptions": {
"fareType": [
"PUBLISHED"
],
"includedCheckedBagsOnly": true
},
"validatingAirlineCodes": [],
"travelerPricings": [{
"travelerId": "1",
"fareOption": "STANDARD",
"travelerType": "ADULT",
"price": {
"currency": "VND",
"total": "1640000.00",
"base": "1381000.00"
},
"fareDetailsBySegment": [{
"segmentId": "9",
"cabin": "ECONOMY",
"fareBasis": "JSP",
"class": "J",
"includedCheckedBags": {
"weight": 20,
"weightUnit": "KG"
}
}]
}]
},
Keep in mind that right now the only source for prices in the API is GDS. Many LCCs don't / only load their more expensive fares into GDS, as it costs them money.
Lately, many "normal" airlines have also added fees when booking from a GDS compared to directly on their website / or other direct distribution methods.
I assume VietJet is one of those carriers, as it is a low-cost airline.
Regarding your second question: That is because of the fare system in the airline industry. Airlines load so called "fares", which specifies the price of a ticket for a given route within a date window.
An example: VietJet offers SGN-DAD for a base fare of 55EUR ( without taxes& fees ). You can choose any flight by VJ on any date within the window of the fare, and the price will be the same, as long as there is availability in the booking class J , which the fare is for.

Low-Fare endpoint returning JSON with missing operating.carrierCode

The Low-fare endpoint just recently started returning JSON with some flight segments missing a key-value pair for operating.carrierCode, for example:
"operating": {
"number": “5898"
This was the second flight segment of the first result (data[0].offerItems[0].services[0].segments[1].flightSegment) when yesterday I searched:
https://test.api.amadeus.com/v1/shopping/flight-offers?origin=LON&destination=PAE&departureDate=2019-10-29&returnDate=2019-11-13&adults=1&nonStop=false&max=50
Here it is in context:
{
"data": [
{
"type": "flight-offer",
"id": "1564934270644-1482530186",
"offerItems": [
{
"services": [
{
"segments": [
{
"flightSegment": {
"departure": {
"iataCode": "LHR",
"terminal": "2",
"at": "2019-10-29T09:20:00Z"
},
"arrival": {
"iataCode": "SFO",
"terminal": "I",
"at": "2019-10-29T13:30:00-07:00"
},
"carrierCode": "SN",
"number": "9101",
"aircraft": {
"code": "777"
},
"operating": {
"carrierCode": "UA",
"number": "9101"
},
"duration": "0DT11H10M"
},
"pricingDetailPerAdult": {
"travelClass": "ECONOMY",
"fareClass": "K",
"availability": 4,
"fareBasis": "KLP5ULGT"
}
},
{
"flightSegment": {
"departure": {
"iataCode": "SFO",
"terminal": "3",
"at": "2019-10-29T16:15:00-07:00"
},
"arrival": {
"iataCode": "PAE",
"at": "2019-10-29T18:32:00-07:00"
},
"carrierCode": "UA",
"number": "5898",
"aircraft": {
"code": "E7W"
},
"operating": {
"number": “5898”
},
"duration": "0DT2H17M"
},
"pricingDetailPerAdult": {
"travelClass": "ECONOMY",
"fareClass": "K",
"availability": 9,
"fareBasis": "KLP5ULGT"
}
}
]
…
Is this a known bug? It was pretty easy to write a workaround, but I was surprised that this data was missing since it had been working correctly for months.
This is a common issue with the operating carrier even in cryptic mode
FLT/DATE RTNG CKIN TM DEP ARR TM EQP ML DURA DIST
UA5898 Y 29OCT SFOPAE 3 415P 632P E7W G 2:17 711
SFOPAE OPERATED BY SKYWEST DBA UNITED EXPRES
>
Whilst at shopping using enterprise apis you can use the same text describing the schedule data resumed by flight number.
Dont know of any parameter to get it in the api response too.

How to add the payment transaction status in order placed by using Demandware OCAPI?

I'm developing API for the mobile app of e-commerce website which is on Demandware. I am using the OCAPI 18.8 to place an order and send the payment details to third-party payment processor which is Vantiv. I get the transaction ID and response code from Vantiv and want to update my order to store these payment transaction details into my order. But I could not find any resource in OCAPI which let me add the transaction Id and response code received from Vantiv. Below is the order which I have placed through OCAPI:
{
"_v": "18.8",
"_type": "order",
"_resource_state": "xyz",
"adjusted_merchandize_total_tax": 0,
"adjusted_shipping_total_tax": 0,
"billing_address": {
"_type": "order_address",
"city": "Boston",
"country_code": "US",
"first_name": "John",
"full_name": "John Martin",
"id": "xyz",
"last_name": "Martin"
},
"channel_type": "storefront",
"confirmation_status": "not_confirmed",
"created_by": "Customer",
"creation_date": "2018-11-20T10:37:58.055Z",
"currency": "USD",
"customer_info": {
"_type": "customer_info",
"customer_id": "xyz",
"customer_name": "Ammar Shahbaz",
"customer_no": "xyz"
},
"customer_name": "Ammar Shahbaz",
"export_status": "not_exported",
"last_modified": "2018-11-20T10:37:58.376Z",
"merchandize_total_tax": 0,
"notes": {
"_type": "simple_link",
"link": "link"
},
"order_no": "123",
"order_token": "xyz",
"order_total": 299.8,
"payment_instruments": [
{
"_type": "order_payment_instrument",
"amount": 299.8,
"payment_card": {
"_type": "payment_card",
"card_type": "Visa",
"credit_card_expired": false,
"expiration_month": 1,
"expiration_year": 2021,
"holder": "John Doe",
"masked_number": "************4240",
"number_last_digits": "4240"
},
"payment_instrument_id": "xyz",
"payment_method_id": "CREDIT_CARD"
}
],
"payment_status": "not_paid",
"product_items": [
{
"_type": "product_item",
"adjusted_tax": 0,
"base_price": 149.9,
"bonus_product_line_item": false,
"gift": false,
"item_id": "xyz",
"item_text": "Long Sleeve Sequin Shift Dress",
"price": 299.8,
"price_after_item_discount": 299.8,
"price_after_order_discount": 299.8,
"product_id": "xyz",
"product_name": "Dress",
"quantity": 2,
"shipment_id": "xyz",
"tax": 0,
"tax_basis": 299.8,
"tax_class_id": "xyz",
"tax_rate": 0,
"c_cost": 25.17,
"c_finalSale": false,
"c_outlet": false,
"c_taxClassID": "xyz"
}
],
"product_sub_total": 299.8,
"product_total": 299.8,
"shipments": [
{
"_type": "shipment",
"adjusted_merchandize_total_tax": 0,
"adjusted_shipping_total_tax": 0,
"gift": false,
"merchandize_total_tax": 0,
"product_sub_total": 299.8,
"product_total": 299.8,
"shipment_id": "xyz",
"shipment_total": 299.8,
"shipping_address": {
"_type": "order_address",
"city": "Boston",
"country_code": "US",
"first_name": "John",
"full_name": "John Martin",
"id": "xyz",
"last_name": "Martin"
},
"shipping_method": {
"_type": "shipping_method",
"description": "Order received within 5-8 business days",
"id": "xyz",
"name": "Standard",
"price": 0,
"shipping_promotions": [
{
"_type": "shipping_promotion",
"callout_msg": "Free shipping on U.S. orders of $125+",
"link": "link",
"promotion_id": "xyz",
"promotion_name": "Free Shipping With $125 Purchase"
}
],
"c_BxFlatrateFlag": false,
"c_IsBorderlinxMethod": false
},
"shipping_status": "not_shipped",
"shipping_total": 0,
"shipping_total_tax": 0,
"tax_total": 0
}
],
"shipping_items": [
{
"_type": "shipping_item",
"adjusted_tax": 0,
"base_price": 0,
"item_id": "xyz",
"item_text": "Shipping",
"price": 0,
"price_after_item_discount": 0,
"shipment_id": "xyz",
"tax": 0,
"tax_basis": 0,
"tax_class_id": "xyz",
"tax_rate": 0
}
],
"shipping_status": "not_shipped",
"shipping_total": 0,
"shipping_total_tax": 0,
"site_id": "site name",
"status": "created",
"taxation": "net",
"tax_total": 0
}
I have tried this resource
Patch /orders/{order_no}/payment_instruments/{payment_instrument_id}
{
"amount" : 299.8,
"payment_card" : {
"number":"424459xxxxxx4240",
"security_code":"121",
"holder":"John Martin",
"card_type":"Visa",
"expiration_month":1,
"expiration_year":2021
},
"payment_method_id" : "CREDIT_CARD",
"c_PaymentProcessor": "VANTIV_CREDIT",
"c_paymentTransaction": {
"custom": {
"litleAFTresponse": "Approved",
"litleAFTTxnId": "8283868xxx8288282"
}
}
}
to update my order but no success.
Please let me know if you have any suggestion. Thanks.
If you have payment auth occurring outside of commerce cloud for some reason, you may be able to handle things in custom request document attributes. Note that there's an option to skip 'authorization' in CC by the skip_authorization parameter. eg:
POST /shop/v19_3/orders/00000027/payment_instruments?skip_authorization=true HTTP/1.1
Host: example.com
Authorization:Bearer eyJfdiI6IjXXXXXX.eyJfdiI6IjEiLCJleHAXXXXXXX.-d5wQW4c4O4wt-Zkl7_fiEiALW1XXXX
Content-Type: application/json
{
"amount": 49.99,
"payment_method_id": "MY_PAYMENT_METHOD",
"c_payment_token": "tokenvaluehere==",
"c_payment_status": "payment_status"
}
Then within your dw.ocapi.shop.order.payment_instrument.afterPOST you could add attributes to the Order's PaymentInstrument via the B2C API methods which are accessible via the callback's order parameter.
You'll want to check in the beforePOST hook to ensure that the c_payment_status param is an acceptable value and if not return a Status.ERROR type of status object. Then you can actually save the properties in the afterPOST hook where the objects you'll need are already created.
For example:
exports.paymentInstrumentAfterPOST = function(order, paymentInstrumentRequest) {
const PaymentTransaction = require('dw/order/PaymentTransaction');
const Status = require('dw/system/Status');
const Transaction = require('dw/system/Transaction');
let methodId = paymentInstrumentRequest.payment_method_id;
let instruments = order.getPaymentInstruments(methodId);
let instrument = instruments[0]; // FIXME you should actually iterate over this instead; just for demo
let paymentTransaction = instrument.getPaymentTransaction();
Transaction.begin();
paymentTransaction.setTransactionID(paymentInstrumentRequest.c_payment_token);
paymentTransaction.setType(PaymentTransaction.TYPE_AUTH);
Transaction.commit();
return new Status(Status.OK);
}
For more info on customizing the payment flow, see the Orders resource documentation
Disclaimer this is all code written free-hand in StackOverflow's answer form. I have not validated that this will actually run, but I hope it provides direction.
Internally in commerce cloud the below method call sets the transaction id: paymentInstrument.paymentTransaction.setTransactionID(anTransactionId) so your assumption is correct. This field is however not exposed in the shop API. From the documentation is is clear that the authorization of the payment should be triggered by commerce cloud. this is a security constraint. It is possible to customize the API to circumvent this limitation.
The platform itself has some internal workflows that you must follow step by step to complete an order via OCAPI Rest Api. You should follow the step by step workflow or if you don't find it ask your DW architect to guide you.
As of today, the platform provides a better way to handle this requirement. Under DATA API Endpoints you have now several entires to update overall order status, payment, shipment, or even shipping address. More details under official release notes:
You can now use Data API endpoints to update orders in server-to-server use cases, such as when an order management system or payment provider initiates a change.
Use new PUT commands to update the different types of order statuses.
PUT /sites/{site_id}/orders/{order_no}/confirmation_status
PUT /sites/{site_id}/orders/{order_no}/export_status
PUT /sites/{site_id}/orders/{order_no}/external_status
PUT /sites/{site_id}/orders/{order_no}/payment_status
PUT /sites/{site_id}/orders/{order_no}/shipping_status
PUT /sites/{site_id}/orders/{order_no}/status
Use a new PUT command to update an order’s shipping address.
PUT /sites/{site_id}/orders/{order_no}/shipments/{shipment_id}/shipping_address
Use new PATCH commands to update order and payment attributes.
PATCH /sites/{site_id}/orders/{order_no}
PATCH /sites/{site_id}/orders/{order_no}/payment_instruments/{payment_instrument_id}
PATCH /sites/{site_id}/orders/{order_no}/payment_instruments/{payment_instrument_id}/transaction
source: https://help.salesforce.com/articleView?id=sf.b2c_20_2_W6833203_ocapi_order_update_endpoints_as.htm&type=5