Tutorial: Retrieve Requirements for a Trip

Enrich your booking flow with personalized travel rules.

Overview

Sherpa provides personalized travel rules to travellers based on their itinerary and traveller profile. Let's see how to display this information with a single API call.

This new improved Trips v3 API will help to simplify the process of displaying travel requirements data for a single trip. In the new API, we introduce a new concept which is Travel Nodes.

Use case

Display personalized travel rules for a traveller going on a round trip from A to B. This information can be displayed during a search or after a booking is made.

Solution

We strive to provide a simple, convenient and understandable experience for travellers. Complex scenarios depend on two factors: who you are as an individual traveller and your itinerary. Our v3/trips endpoint takes that information as an input and provides you with a structured way to create custom user interfaces.

Steps:

  • Learn to create a Trip and Traveller
  • Make an API request
  • Review the response
  • Display the information in your UI To better illustrate the capabilities of the v3/trips Endpoint of the Travel Restriction API, we'll be breaking down one of our own solutions and show how you can recreate that very same experience. This way you can ensure that the information you provide to your travellers is always accurate and updated.

1. Learn to create a Trip and Traveller

In this tutorial, we are taking a one-way trip as a fully vaccinated traveller with a Canadian passport, going from Toronto, Canada (YYZ) to Vietnam (SGN).

Both data points are highly relevant as they provide a personalized experience.

📘 Information about the traveller is not available

In case you might not know the passport a traveller is travelling with, we recommend assuming the nationality of the origin. In our example, it would be "Canadian" for travellers starting their journey in Canada.

We recommend that you provide your travellers with the ability to specify their passport, as well as their vaccination status, as these can drastically change the travel requirements that apply.

2. Make an API request

The following example shows the JSON payload that has to be formalized as an API request.

Example
{
  "data": {
    "type": "TRIP",
    "attributes": {
      "traveller": {
        "passports": ["CAN"]
      },
      "locale": "en-US",
      "travelNodes": [
        {
          "type": "ORIGIN",
          "departure": {
            "date": "2022-09-12",
            "time": "00:00",
            "travelMode": "AIR"
          },
          "airportCode": "YYZ"
        },
        {
          "type": "DESTINATION",
          "arrival": {
            "date": "2022-09-12",
            "time": "00:00",
            "travelMode": "AIR",
            "flightNumber": "AB1234"
          },
          "airportCode": "SGN"
        }
      ]
    }
  }
}

3. Review the response

Looking at the API response returned from the v3/trips endpoint, we can find all relevant information required to show the Summary banner.

JSON
{
    "meta": {
        "copyright": "Sherpa",
        "version": "3.0.0"
    },
    "data": {
        "id": "6c85bb5e-4758-49b4-94f9-96772e7e1f25",
        "type": "TRIP",
        "attributes": {
            "headline": "Most travelers from Toronto, YYZ can enter Vietnam, but there are restrictions.",
            "traveller": {
                "passports": [
                    "CAN"
                ],
                "vaccinations": [
                    {
                        "type": "COVID_19",
                        "status": "NOT_VACCINATED"
                    }
                ]
            },
            "locale": "en-US",
            "travelNodes": [
                {
                    "type": "ORIGIN",
                    "departure": {
                        "date": "2022-09-12",
                        "time": "00:00",
                        "travelMode": "AIR"
                    },
                    "airportCode": "YYZ",
                    "airportName": "Toronto"
                },
                {
                    "type": "DESTINATION",
                    "arrival": {
                        "date": "2022-09-12",
                        "time": "00:00",
                        "travelMode": "AIR",
                        "flightNumber": "AB1234"
                    },
                    "locationCode": "VNM",
                    "locationName": "Vietnam"
                }
            ],
            "informationGroups": [
                {
                    "name": "Visa Requirements",
                    "headline": "",
                    "tooltip": "Visa requirements are determined by the passport you are travelling with and duration of your trip.",
                    "groupings": [
                        {
                            "name": "Toronto",
                            "headline": "",
                            "enforcement": "MAY_BE_REQUIRED",
                            "data": []
                        },
                        {
                            "name": "Vietnam",
                            "headline": "",
                            "enforcement": "MAY_BE_REQUIRED",
                            "data": [
                                {
                                    "type": "PROCEDURE",
                                    "id": "ee0ba620-ff83-42c0-a23a-f3a944a78e74"
                                }
                            ]
                        }
                    ]
                },
                {
                    "name": "Quarantine",
                    "headline": "",
                    "groupings": [
                        {
                            "name": "Toronto",
                            "headline": "",
                            "enforcement": "MAY_BE_REQUIRED",
                            "data": []
                        },
                        {
                            "name": "Vietnam",
                            "headline": "",
                            "enforcement": "MAY_BE_REQUIRED",
                            "data": [
                                {
                                    "type": "PROCEDURE",
                                    "id": "a38954b8-79cd-4cf0-a264-75758a9d9f75"
                                }
                            ]
                        }
                    ]
                },
                {
                    "name": "COVID-19 Testing",
                    "headline": "",
                    "groupings": [
                        {
                            "name": "Toronto",
                            "headline": "",
                            "enforcement": "MAY_BE_REQUIRED",
                            "data": []
                        },
                        {
                            "name": "Vietnam",
                            "headline": "",
                            "enforcement": "MAY_BE_REQUIRED",
                            "data": [
                                {
                                    "type": "PROCEDURE",
                                    "id": "59f0e126-b630-4442-8118-7f57394d6997"
                                }
                            ]
                        }
                    ]
                },
                {
                    "name": "Vaccination / Immunization",
                    "headline": "",
                    "groupings": [
                        {
                            "name": "Toronto",
                            "headline": "",
                            "enforcement": "MAY_BE_REQUIRED",
                            "data": []
                        },
                        {
                            "name": "Vietnam",
                            "headline": "",
                            "enforcement": "MAY_BE_REQUIRED",
                            "data": []
                        }
                    ]
                },
                {
                    "name": "Other Documents",
                    "headline": "",
                    "groupings": [
                        {
                            "name": "Toronto",
                            "headline": "",
                            "enforcement": "MAY_BE_REQUIRED",
                            "data": []
                        },
                        {
                            "name": "Vietnam",
                            "headline": "",
                            "enforcement": "MAY_BE_REQUIRED",
                            "data": []
                        }
                    ]
                },
                {
                    "name": "Additional Information",
                    "headline": "",
                    "groupings": [
                        {
                            "name": "Toronto",
                            "headline": "",
                            "enforcement": "MAY_BE_REQUIRED",
                            "data": []
                        },
                        {
                            "name": "Vietnam",
                            "headline": "",
                            "enforcement": "MAY_BE_REQUIRED",
                            "data": [
                                {
                                    "type": "PROCEDURE",
                                    "id": "14b5ef3e-b205-438c-98aa-946f5bf85655"
                                },
                                ...
                            ]
                        }
                    ]
                },
                {
                    "name": "Upcoming",
                    "headline": "",
                    "tooltip": "Some of these changes may not be in effect yet and may change unexpectedly.",
                    "groupings": [
                        {
                            "name": "Toronto",
                            "headline": "",
                            "enforcement": "MAY_BE_REQUIRED",
                            "data": []
                        },
                        {
                            "name": "Vietnam",
                            "headline": "",
                            "enforcement": "MAY_BE_REQUIRED",
                            "data": [
                                {
                                    "type": "PROCEDURE",
                                    "id": "14b5ef3e-b205-438c-98aa-946f5bf85655"
                                },
                                ...
                            ]
                        }
                    ]
                }
            ]
        },
        "relationships": {
            "restrictions": {
                "meta": {
                    "count": 2
                },
                "data": [
                    {
                        "type": "RESTRICTION",
                        "id": "58a03960-6732-419b-a0d5-abc83e2f7341"
                    },
                    ...
                ]
            },
            "procedures": {
                "meta": {
                    "count": 10
                },
                "data": [
                    {
                        "type": "PROCEDURE",
                        "id": "ee0ba620-ff83-42c0-a23a-f3a944a78e74"
                    },
                    ...
                ]
            }
        }
    },
    "included": [
        {
            "id": "ee0ba620-ff83-42c0-a23a-f3a944a78e74",
            "type": "PROCEDURE",
            "attributes": {
                "category": "DOC_REQUIRED",
                "subCategory": "BEFORE_ARRIVAL",
                "location": "VNM",
                "title": "Electronic visitor visa",
                "description": "To visit Vietnam for Business or Tourism, you require a visa.\n\nAn eVisa is the fastest and easiest way of obtaining a Vietnam visa as you can submit an application and supporting documents online. If approved, you'll receive your eVisa confirmation electronically. When you arrive in Vietnam, border crossing will ask for your passport and eVisa to ensure you have the proper visas.\n\nFor all other visas, visit the government site.",
                "more": [
                    "Entry to Vietnam with an eVisa is supported at 8 airports, 13 land borders, and 7 seaports."
                ],
                "documentLinks": [
                    {
                        "type": "LINK",
                        "provider": "sherpa",
                        "title": "Apply online",
                        "intent": "apply-product",
                        "url": "https://sherpa-widget.joinsherpa.io/applications/products/VNM_EVISA?affiliateId=sherpa&language=en-US",
                        "productId": "VNM_EVISA",
                        "product": {
                            "name": "Vietnamese eVisa",
                            "price": {
                                "value": 45,
                                "currency": "USD"
                            },
                            "destinations": [
                                "Vietnam"
                            ],
                            "travelPurposes": [
                                "Tourism",
                                "Business"
                            ]
                        }
                    }
                ],
                "source": {
                    "sourceType": "GOVERNMENT",
                    "title": "Ministry of Foreign Affairs of Vietnam",
                    "url": "https://lanhsuvietnam.gov.vn/Lists/ChuyenMuc/ChuyenMuc/ChuyenMuc.aspx?List=b6a96952%2D5329%2D4042%2D901b%2D2af247f16b68&ID=24"
                },
                "lastUpdatedAt": "2022-07-08T02:39:00.000Z",
                "createdAt": "2021-10-07T10:58:00.000Z",
                "startDate": null,
                "endDate": null,
                "enforcement": "MANDATORY",
                "documentType": [
                    "E_VISA"
                ],
                "tags": [
                    "international",
                    "fully_vaccinated",
                    "not_vaccinated",
                    "land",
                    "air",
                    "sea",
                    "tourism",
                    "business"
                ],
                "travelPurpose": [
                    "TOURISM",
                    "BUSINESS"
                ],
                "lengthOfStay": [
                    {
                        "value": 30,
                        "type": "DAYS",
                        "text": "30 days"
                    }
                ],
                "included": [
                    {
                        "code": "AND",
                        "text": "Andorra",
                        "type": "NATIONALITY"
                    },
                    ...
                ],
                "icon": {
                    "name": "visa"
                }
            }
        },
        ...
    ]
}

4. Display the information in your UI

To find the Trip Summary, we'll be leveraging the attribute data.attributes.headline.

Show detailed travel rules

Each individual segment provides you with a summary of travel rules, which are grouped under various categories. Restrictions and Procedures might find their way into multiple groupings.

For the user interface on our WebApp solution, we opted to group multiple groupings together to further simplify the flexible API response.

The new Trips v3 provides simplified groupings that you can retrieve data and display directly on the front end. All of the groupings are organized by location name under "informationGroups". Under this group, you will find data for each segment such as Travel Restrictions, Visa Requirements, Quarantine, COVID-19 Testing, Vaccination / Immunization, Other Documents, Additional Information, and Upcoming with their tooltip if it exists. The naming & tooltip are already translated into different languages.

For displaying restrictions for procedures for each segment, we can find that information under data.attributes.informationGroups[x].groupings.

❗️ Nested Grouping

An object of type grouping may include a list of the same type (grouping[]) as the value for the optional parameter groupings.
This means that to get the first restrictionId in a particular information grouping, you might need to look at informationGrouping[x].groupings[0].data[0] or you might need to look at informationGrouping[x].groupings[0].groupings[0].groupings[0].data[0]. While there are no technical limits on the number of allowed nesting layers, we will keep this structure limited to a maximum of 5.
This nested structure allows us to be flexible in delivering the hierarchy of information without changing the API response format. While this example currently looks at data sorted only based on grouping, it is vital to make sure that your application can handle the nested structure of groupings. For more information, look at this

In this example, data is also grouped by location, so it'll easier to show the restrictions that belong to a specific location without further transformation.

Tutorial Retrieve Requirements

Show document checklist

Displaying an all-in-one checklist for all the required documents can be seen by looking at the groupings with the type DOC_REQUIRED.

This grouping list will include all documents related to visa requirements, COVID-19 testing, as well as various other types of documents.

Optional: Travel rules for returning home

In the new API, Round trips can be retrieved by sending another request to v3/trips endpoint. It will be entirely new travel nodes and be treated as a separate trip.

The API response will be the as the departure trip. We can apply the same strategy of mapping the response to a user interface to the return segment as well.

Optional: Travel rules for connecting flights

Trips v3 supports up to 3 transit nodes.

Below is an example payload of a trip with two transit nodes (Seattle & Seoul).

The full itinerary is: Washington (IAD) -> Seattle (SEA) -> Seoul (ICN) -> Da Nang (DAD).

Request
Response
{
"data": {
  "type": "TRIP",
  "attributes": {
    "traveller": {
      "passports": [
        "USA"
      ],
      "vaccinations": [
        {
          "type": "COVID_19",
          "status": "FULLY_VACCINATED"
        }
      ]
    },
    "locale": "en-US",
    "travelNodes": [
      {
        "type": "ORIGIN",
        "departure": {
          "date": "2023-10-23",
          "time": "00:00"
        },
        "airportCode": "IAD"
      },
      {
        "type": "TRANSIT",
        "departure": {
          "date": "2023-10-23",
          "time": "00:00"
        },
        "arrival": {
          "date": "2023-10-23",
          "time": "00:00",
          "flightNumber": "AB1234"
        },
        "airportCode": "SEA"
      },
      {
        "type": "TRANSIT",
        "departure": {
          "date": "2023-10-23",
          "time": "00:00"
        },
        "arrival": {
          "date": "2023-10-23",
          "time": "00:00",
          "flightNumber": "CD5678"
        },
        "airportCode": "ICN"
      },
      {
        "type": "DESTINATION",
        "arrival": {
          "date": "2023-10-23",
          "time": "00:00",
          "flightNumber": "EF9012"
        },
        "airportCode": "DAD"
      }
    ]
  }
}
}

Display Requirements Recursively

The response of /v3/trips includes procedures and restrictions that apply to a particular trip, organized in data.attributes.informationGroups as a list. Each InformationGroup object has a property called groupings that is a list of the type Grouping. It is important to note that each grouping again may have a property named groupings of type array Grouping, so it is essential to navigate this object recursively to not lose any data in case the API response part that contains procedures & restrictions are nested for multiple level. Here is a sample code that can render the information in a particular Group on a frontend component

JavaScript
function processGroupings(groupings, htmlElement) {
  groupings.forEach((grouping) => {
    // Use grouping information to display heading, titles, etc.
    htmlElement.innerHTML += `<div class='grouping-name'>${grouping.name}</div>`;

    grouping.data.forEach((requirement) =>
      // Display the requirements a& procedures in the grouping based on the id
      displayRequirement(requirement.id, htmlElement),
    );

    // Call the same function on the child groupings if they exist
    if (grouping.groupings) {
      processGroupings(groupings.groupings, htmlElement);
    }
  });
}

A working example of such a function is used here to display all visa requirements.