Metodo Get BulkTripOptions

Rispetto al metodo GetTripOptions, il metodo GetBulkTripOptions presenta i seguenti vantaggi:

  • Consente un popolamento più efficiente della cache di Google, utilizzando meno richieste e allineandosi meglio alle API upstream degli operatori che possono essere utilizzate dai partner per acquisire i dati.
  • Semplifica la fornitura dei dati per i partner con un insieme predeterminato di viaggi disponibili senza un'ispezione dettagliata dell'itinerario.
  • Per i partner più sofisticati, fornisce comunque un elenco di itinerari noti per massimizzare la corrispondenza tra l'inventario dei partner e gli itinerari prodotti dal motore di routing di Google, in modo da mostrare i prezzi dei partner nel maggior numero possibile di itinerari.
  • Consente di importare itinerari che Google non pubblica ancora, per potenzialmente regolare il motore di routing di Google in modo che corrisponda meglio all'inventario dei partner in futuro.

GetBulkTripOptionsRequest

Proto Definition

// Request sent to partners.
message GetBulkTripOptionsRequest {
  // The MarketDates for which to return results.
  // Initially, only a single value will be supplied, representing one-way
  // trips.
  repeated MarketDate market_dates = 1;

  // List of itineraries matching market_dates that Google knows about and will
  // serve to end users. Partners should try to return results matching these
  // itineraries, as other itineraries will not be immediately useful other than
  // for analysis purposes.
  repeated ItineraryKey known_itineraries = 2;

  // If true, only the explicitly specified known_itineraries should be
  // returned. Not in use yet (always set to false).
  bool only_known_itineraries = 3;
}

message MarketDate {
  // ID of the stop where the traveler starts their journey.
  string origin_ticketing_stop_id = 1;

  // Stop ID of the ultimate journey destination of the traveler.
  string destination_ticketing_stop_id = 2;

  // Date of departure at the origin, in the timezone at the origin.
  .google.type.Date departure_date = 3;
}

// A full end-to-end journey for a traveler, including all vehicles used.
message ItineraryKey {
  // All segments together should form a single trip for which a ticket can be
  // booked.
  repeated ext.travel.transport.partner.SegmentKey segment_keys = 1;
}

Esempio JSON

{
  "market_dates": [
    {
      "origin_ticketing_stop_id": "ZRH-1234",
      "destination_ticketing_stop_id": "WOL-2455",
      "departure_date": {
        "year": 2023,
        "month": 5,
        "day": 15
      }
    }
  ],
  "known_itineraries": [
    {
      "segment_keys": [
        {
          "ticketing_trip_id": "123456",
          "from_ticketing_stop_time_id": "ZRH-1234",
          "to_ticketing_stop_time_id": "LUZ-1235",
          "service_date": {
            "year": 2023,
            "month": 5,
            "day": 15
          },
          "boarding_time": {
            "year": 2023,
            "month": 5,
            "day": 15,
            "hours": 14,
            "minutes": 25,
            "seconds": 0,
            "nanos": 0,
            "utc_offset": "0s"
          },
          "arrival_time": {
            "year": 2023,
            "month": 5,
            "day": 15,
            "hours": 16,
            "minutes": 25,
            "seconds": 0,
            "nanos": 0,
            "utc_offset": "0s"
          }
        },
        {
          "ticketing_trip_id": "988833",
          "from_ticketing_stop_time_id": "LUZ-1235",
          "to_ticketing_stop_time_id": "WOL-2455",
          "service_date": {
            "year": 2023,
            "month": 5,
            "day": 15
          },
          "boarding_time": {
            "year": 2023,
            "month": 5,
            "day": 15,
            "hours": 18,
            "minutes": 13,
            "seconds": 0,
            "nanos": 0,
            "utc_offset": "0s"
          },
          "arrival_time": {
            "year": 2023,
            "month": 5,
            "day": 15,
            "hours": 20,
            "minutes": 13,
            "seconds": 0,
            "nanos": 0,
            "utc_offset": "0s"
          }
        }
      ]
    },
    {
      "segment_keys": [
        {
          "ticketing_trip_id": "98765",
          "from_ticketing_stop_time_id": "ZRH-1234",
          "to_ticketing_stop_time_id": "ZUG-1235",
          "service_date": {
            "year": 2023,
            "month": 5,
            "day": 15
          },
          "boarding_time": {
            "year": 2023,
            "month": 5,
            "day": 15,
            "hours": 14,
            "minutes": 30,
            "seconds": 0,
            "nanos": 0,
            "utc_offset": "0s"
          },
          "arrival_time": {
            "year": 2023,
            "month": 5,
            "day": 15,
            "hours": 16,
            "minutes": 30,
            "seconds": 0,
            "nanos": 0,
            "utc_offset": "0s"
          }
        },
        {
          "ticketing_trip_id": "43210",
          "from_ticketing_stop_time_id": "ZUG-1235",
          "to_ticketing_stop_time_id": "WOL-2455",
          "service_date": {
            "year": 2023,
            "month": 5,
            "day": 15
          },
          "boarding_time": {
            "year": 2023,
            "month": 5,
            "day": 15,
            "hours": 18,
            "minutes": 13,
            "seconds": 0,
            "nanos": 0,
            "utc_offset": "0s"
          },
          "arrival_time": {
            "year": 2023,
            "month": 5,
            "day": 15,
            "hours": 20,
            "minutes": 13,
            "seconds": 0,
            "nanos": 0,
            "utc_offset": "0s"
          }
        }
      ]
    }
  ],
  "only_known_itineraries": false
}

GetBulkTripOptionsResponse

Proto Definition

// Response received from partners.
message GetBulkTripOptionsResponse {
  oneof response {
    BulkTripOptionsResult bulk_trip_options_result = 1;
    BulkTripOptionsError bulk_trip_options_error = 2;
  }
}

// A message representing a successful response.
message BulkTripOptionsResult {
  // One response per entry in known_itineraries in the request, plus any
  // additional ones partners choose to return if only_known_itineraries is
  // false.
  repeated ItineraryResponse itinerary_responses = 1;
}

// A message for errors affecting the whole request.
message BulkTripOptionsError {
  enum BulkTripOptionsErrorType {
    // An unexpected error happened during retrieval of this trip.
    // This indicates a bug that needs to be fixed by the partner.
    // This error is retriable.
    // Always returns HTTP 500 status code in response.
    INTERNAL_ERROR = 1;
  }

  BulkTripOptionsErrorType error_type = 1;

  // This is not user-visible and is for logging and debugging purposes only.
  string error_message = 2;
}

// A message container for an itinerary with a set of prices for that itinerary.
message ItineraryResponse {
  // A single itinerary that this response relates to.
  ItineraryKey itinerary = 1;

  oneof response {
    // A set of prices for this itinerary.
    TripOptionSet trip_option_set = 2;

    // Error information about the retrieval of this itinerary.
    TripOptionsError trip_options_error = 3;
  }
}

// A container for multiple trip options.
message TripOptionSet {
  // To reduce the amount of data transferred, segments.segment_key can be empty
  // inside these trip_options, since the segment_key is already present in
  // ItineraryResponse.itinerary.segment_keys. This requires the number of
  // segments in to each TripOption to match exactly the number of segments
  // inside ItineraryResponse.itinerary. We then assume that the n-th
  // trip_options.segments.segment_key matches the n-th itinerary.segment_key.
  repeated TripOption trip_options = 1;
}


// A travel option for users covering the whole end-to-end journey with the
// partner.
message TripOption {
  // A series of Segments that cover the whole trip option, one for each
  // SegmentKey in the request.
  repeated Segment segments = 1;

  // This is the lowest standard fare of all seats with the specified segments.
  // This field is optional if the series of segments is unavailable.
  // This "standard fare" should be the lowest seat price where no age or other
  // booking restrictions apply. The currency should be the local currency of
  // the origin of the first segment.
  Fare lowest_standard_fare = 2;

  // The availability status for bookings of this trip option at the
  // lowest_standard_fare.
  Availability availability = 3;

  // This is used to receive optional extra data via the Travel Transport API
  // and pass it into the ticketing deep link.
  // Booking links should still work without the booking token, but the token
  // can be used to ensure price consistency between Google Search results and
  // the partner booking page.
  string booking_token = 4 [features.field_presence = EXPLICIT];
}

// A segment traveled on a single vehicle in a given Service Class.
message Segment {
  SegmentKey segment_key = 1;

  // The service class used on this segment.
  ServiceClass service_class = 2;
}

Esempio JSON

{
  "bulk_trip_options_result": {
    "itinerary_responses": [
      {
        "itinerary": {
          "segment_keys": [
            {
              "ticketing_trip_id": "123456",
              "from_ticketing_stop_time_id": "ZRH-1234",
              "to_ticketing_stop_time_id": "LUZ-1235",
              "service_date": {
                "year": 2023,
                "month": 5,
                "day": 15
              },
              "boarding_time": {
                "year": 2023,
                "month": 5,
                "day": 15,
                "hours": 14,
                "minutes": 25,
                "seconds": 0,
                "nanos": 0,
                "utc_offset": "0s"
              },
              "arrival_time": {
                "year": 2023,
                "month": 5,
                "day": 15,
                "hours": 16,
                "minutes": 25,
                "seconds": 0,
                "nanos": 0,
                "utc_offset": "0s"
              }
            },
            {
              "ticketing_trip_id": "988833",
              "from_ticketing_stop_time_id": "LUZ-1235",
              "to_ticketing_stop_time_id": "WOL-2455",
              "service_date": {
                "year": 2023,
                "month": 5,
                "day": 15
              },
              "boarding_time": {
                "year": 2023,
                "month": 5,
                "day": 15,
                "hours": 18,
                "minutes": 13,
                "seconds": 0,
                "nanos": 0,
                "utc_offset": "0s"
              },
              "arrival_time": {
                "year": 2023,
                "month": 5,
                "day": 15,
                "hours": 20,
                "minutes": 13,
                "seconds": 0,
                "nanos": 0,
                "utc_offset": "0s"
              }
            }
          ]
        },
        "trip_option_set": {
          "trip_options": [
            {
              "segments": [
                {
                  "service_class": {
                    "type": "SECOND_CLASS"
                  }
                },
                {
                  "service_class": {
                    "type": "SECOND_CLASS"
                  }
                }
              ],
              "lowest_standard_fare": {
                "total_amount": {
                  "units": 10,
                  "nanos": 0,
                  "currency_code": "CHF"
                },
                "line_items": [
                  {
                    "line_item_type": "BASE_FARE",
                    "amount": {
                      "units": 9,
                      "nanos": 750000000,
                      "currency_code": "CHF"
                    }
                  },
                  {
                    "line_item_type": "SERVICE_CHARGE",
                    "amount": {
                      "units": 0,
                      "nanos": 250000000,
                      "currency_code": "CHF"
                    }
                  }
                ]
              },
              "availability": {
                "available": {
                  "available_seat_count": 44,
                  "total_seat_count": 200
                }
              }
            },
            {
              "segments": [
                {
                  "service_class": {
                    "type": "FIRST_CLASS"
                  }
                },
                {
                  "service_class": {
                    "type": "FIRST_CLASS"
                  }
                }
              ],
              "lowest_standard_fare": {
                "total_amount": {
                  "units": 15,
                  "nanos": 0,
                  "currency_code": "CHF"
                },
                "line_items": [
                  {
                    "line_item_type": "BASE_FARE",
                    "amount": {
                      "units": 13,
                      "nanos": 950000000,
                      "currency_code": "CHF"
                    }
                  },
                  {
                    "line_item_type": "SERVICE_CHARGE",
                    "amount": {
                      "units": 1,
                      "nanos": 50000000,
                      "currency_code": "CHF"
                    }
                  }
                ]
              },
              "availability": {
                "available": {
                  "available_seat_count": 10,
                  "total_seat_count": 100
                }
              }
            }
          ]
        }
      },
      {
        "itinerary": {
          "segment_keys": [
            {
              "ticketing_trip_id": "98765",
              "from_ticketing_stop_time_id": "ZRH-1234",
              "to_ticketing_stop_time_id": "ZUG-1235",
              "service_date": {
                "year": 2023,
                "month": 5,
                "day": 15
              },
              "boarding_time": {
                "year": 2023,
                "month": 5,
                "day": 15,
                "hours": 14,
                "minutes": 30,
                "seconds": 0,
                "nanos": 0,
                "utc_offset": "0s"
              },
              "arrival_time": {
                "year": 2023,
                "month": 5,
                "day": 15,
                "hours": 16,
                "minutes": 30,
                "seconds": 0,
                "nanos": 0,
                "utc_offset": "0s"
              }
            },
            {
              "ticketing_trip_id": "43210",
              "from_ticketing_stop_time_id": "ZUG-1235",
              "to_ticketing_stop_time_id": "WOL-2455",
              "service_date": {
                "year": 2023,
                "month": 5,
                "day": 15
              },
              "boarding_time": {
                "year": 2023,
                "month": 5,
                "day": 15,
                "hours": 18,
                "minutes": 13,
                "seconds": 0,
                "nanos": 0,
                "utc_offset": "0s"
              },
              "arrival_time": {
                "year": 2023,
                "month": 5,
                "day": 15,
                "hours": 20,
                "minutes": 13,
                "seconds": 0,
                "nanos": 0,
                "utc_offset": "0s"
              }
            }
          ]
        },
        "trip_option_set": {
          "trip_options": [
            {
              "segments": [
                {
                  "service_class": {
                    "type": "SECOND_CLASS"
                  }
                },
                {
                  "service_class": {
                    "type": "SECOND_CLASS"
                  }
                }
              ],
              "lowest_standard_fare": {
                "total_amount": {
                  "units": 9,
                  "nanos": 0,
                  "currency_code": "CHF"
                },
                "line_items": [
                  {
                    "line_item_type": "BASE_FARE",
                    "amount": {
                      "units": 8,
                      "nanos": 750000000,
                      "currency_code": "CHF"
                    }
                  },
                  {
                    "line_item_type": "SERVICE_CHARGE",
                    "amount": {
                      "units": 0,
                      "nanos": 250000000,
                      "currency_code": "CHF"
                    }
                  }
                ]
              },
              "availability": {
                "available": {
                  "available_seat_count": 30,
                  "total_seat_count": 150
                }
              }
            },
            {
              "segments": [
                {
                  "service_class": {
                    "type": "FIRST_CLASS"
                  }
                },
                {
                  "service_class": {
                    "type": "FIRST_CLASS"
                  }
                }
              ],
              "lowest_standard_fare": {
                "total_amount": {
                  "units": 14,
                  "nanos": 0,
                  "currency_code": "CHF"
                },
                "line_items": [
                  {
                    "line_item_type": "BASE_FARE",
                    "amount": {
                      "units": 12,
                      "nanos": 950000000,
                      "currency_code": "CHF"
                    }
                  },
                  {
                    "line_item_type": "SERVICE_CHARGE",
                    "amount": {
                      "units": 1,
                      "nanos": 50000000,
                      "currency_code": "CHF"
                    }
                  }
                ]
              },
              "availability": {
                "available": {
                  "available_seat_count": 15,
                  "total_seat_count": 60
                }
              }
            }
          ]
        }
      }
    ]
  }
}

Esempio di errore JSON

{
  "bulk_trip_options_error": {
    "error_type": "INTERNAL_ERROR",
    "error_message": "Unexpected RoutingException during trip lookup."
  }
}

Errore parziale JSON

{
  "bulk_trip_options_result": {
    "itinerary_responses": [
      {
        "itinerary": {
          "segment_keys": [
            {
              "ticketing_trip_id": "123456",
              "from_ticketing_stop_time_id": "ZRH-1234",
              "to_ticketing_stop_time_id": "LUZ-1235",
              "service_date": {
                "year": 2023,
                "month": 5,
                "day": 15
              },
              "boarding_time": {
                "year": 2023,
                "month": 5,
                "day": 15,
                "hours": 14,
                "minutes": 25,
                "seconds": 0,
                "nanos": 0,
                "utc_offset": "0s"
              },
              "arrival_time": {
                "year": 2023,
                "month": 5,
                "day": 15,
                "hours": 16,
                "minutes": 25,
                "seconds": 0,
                "nanos": 0,
                "utc_offset": "0s"
              }
            },
            {
              "ticketing_trip_id": "988833",
              "from_ticketing_stop_time_id": "LUZ-1235",
              "to_ticketing_stop_time_id": "WOL-2455",
              "service_date": {
                "year": 2023,
                "month": 5,
                "day": 15
              },
              "boarding_time": {
                "year": 2023,
                "month": 5,
                "day": 15,
                "hours": 18,
                "minutes": 13,
                "seconds": 0,
                "nanos": 0,
                "utc_offset": "0s"
              },
              "arrival_time": {
                "year": 2023,
                "month": 5,
                "day": 15,
                "hours": 20,
                "minutes": 13,
                "seconds": 0,
                "nanos": 0,
                "utc_offset": "0s"
              }
            }
          ]
        },
        "trip_option_set": {
          "trip_options": [
            {
              "segments": [
                {
                  "service_class": {
                    "type": "SECOND_CLASS"
                  }
                },
                {
                  "service_class": {
                    "type": "SECOND_CLASS"
                  }
                }
              ],
              "lowest_standard_fare": {
                "total_amount": {
                  "units": 10,
                  "nanos": 0,
                  "currency_code": "CHF"
                },
                "line_items": [
                  {
                    "line_item_type": "BASE_FARE",
                    "amount": {
                      "units": 9,
                      "nanos": 750000000,
                      "currency_code": "CHF"
                    }
                  },
                  {
                    "line_item_type": "SERVICE_CHARGE",
                    "amount": {
                      "units": 0,
                      "nanos": 250000000,
                      "currency_code": "CHF"
                    }
                  }
                ]
              },
              "availability": {
                "available": {
                  "available_seat_count": 44,
                  "total_seat_count": 200
                }
              }
            },
            {
              "segments": [
                {
                  "service_class": {
                    "type": "FIRST_CLASS"
                  }
                },
                {
                  "service_class": {
                    "type": "FIRST_CLASS"
                  }
                }
              ],
              "lowest_standard_fare": {
                "total_amount": {
                  "units": 15,
                  "nanos": 0,
                  "currency_code": "CHF"
                },
                "line_items": [
                  {
                    "line_item_type": "BASE_FARE",
                    "amount": {
                      "units": 13,
                      "nanos": 950000000,
                      "currency_code": "CHF"
                    }
                  },
                  {
                    "line_item_type": "SERVICE_CHARGE",
                    "amount": {
                      "units": 1,
                      "nanos": 50000000,
                      "currency_code": "CHF"
                    }
                  }
                ]
              },
              "availability": {
                "available": {
                  "available_seat_count": 10,
                  "total_seat_count": 100
                }
              }
            }
          ]
        }
      },
      {
        "itinerary": {
          "segment_keys": [
            {
              "ticketing_trip_id": "98765",
              "from_ticketing_stop_time_id": "ZRH-1234",
              "to_ticketing_stop_time_id": "ZUG-1235",
              "service_date": {
                "year": 2023,
                "month": 5,
                "day": 15
              },
              "boarding_time": {
                "year": 2023,
                "month": 5,
                "day": 15,
                "hours": 14,
                "minutes": 30,
                "seconds": 0,
                "nanos": 0,
                "utc_offset": "0s"
              },
              "arrival_time": {
                "year": 2023,
                "month": 5,
                "day": 15,
                "hours": 16,
                "minutes": 30,
                "seconds": 0,
                "nanos": 0,
                "utc_offset": "0s"
              }
            },
            {
              "ticketing_trip_id": "43210",
              "from_ticketing_stop_time_id": "ZUG-1235",
              "to_ticketing_stop_time_id": "WOL-2455",
              "service_date": {
                "year": 2023,
                "month": 5,
                "day": 15
              },
              "boarding_time": {
                "year": 2023,
                "month": 5,
                "day": 15,
                "hours": 18,
                "minutes": 13,
                "seconds": 0,
                "nanos": 0,
                "utc_offset": "0s"
              },
              "arrival_time": {
                "year": 2023,
                "month": 5,
                "day": 15,
                "hours": 20,
                "minutes": 13,
                "seconds": 0,
                "nanos": 0,
                "utc_offset": "0s"
              }
            }
          ]
        },
        "trip_options_error": {
          "error_type": "SEGMENT_KEY_NOT_FOUND",
          "error_message": "No matching segments found, no departures at 14:30"
        }
      }
    ]
  }
}

Scenari tipici

Prevediamo i seguenti scenari con forme di richiesta particolari per l'API:

  • Per i partner meno esperti di tecnologia, è sufficiente fornire un market_date. Questi partner possono utilizzare una query basata su market_date per i dati upstream e restituire tutti i risultati mappati nel nostro formato dei dati. Google può filtrare i risultati in modo da mostrare solo gli itinerari previsti.

  • Per i partner più sofisticati dal punto di vista tecnico, fornisci sia un market_date che un known_itineraries. Il partner può eseguire una ricerca dettagliata nei database interni per poter prezzare esattamente gli itinerari previsti. Tutti gli known_itineraries richiesti verranno mostrati agli utenti, in modo che i partner possano massimizzare il numero di itinerari che mostrano il loro prezzo e il link di prenotazione. I partner hanno ancora la possibilità di restituire itinerari aggiuntivi per aiutare Google a trovare una corrispondenza migliore con il proprio inventario (promosso).

Segnalazione degli errori

Gli errori devono essere segnalati singolarmente per ogni viaggio. Pertanto, la risposta preferita è BulkTripOptionsResult (HTTP 200), che indica gli errori per viaggio in bulk_trip_options_result.itinerary_responses[i].trip_options_error. Se l'intera richiesta non è riuscita in modo imprevisto, utilizza bulk_trip_options_error con BulkTripOptionsErrorType.INTERNAL_ERROR (HTTP 500).

Per ulteriori dettagli, vedi TripOptionsErrorType

Per la restituzione del codice di stato nelle risposte HTTP, consulta la sezione Codici di stato e gestione degli errori.

Note

MarketDate.departure_date specifica un giorno di calendario. Per una migliore corrispondenza con le API dell'operatore, verrà utilizzato il fuso orario dell'origine. Tuttavia, SegmentKey continuerà a specificare gli orari di imbarco e arrivo utilizzando il fuso orario UTC per coerenza con GetTripOptions.