GraphQL concepts
As an integrated partner, you are familiar with our current API formats and standards:
- XML - Markup language that is used to encode documents in human-readable and extensible format.
- REST - Architecture used for exchanging structured data that is performant and ubiquitous, which means partners can easily adopt our APIs to send requests and responses that meet performance metrics crucial to the nature of the traveler business.
- JSON - Lightweight format for structured data that is easy to read and parse. It is used primarily to transmit data between a server and web application as an alternative to XML. (This format will continue to be used. GraphQL queries use the JSON content type and responses are returned in JSON.)
Now, we are offering new capabilities as part of a GraphQL API. Why introduce GraphQL into the mix?
Benefits
GraphQL is a query language that enables you to fetch data efficiently, and it offers these benefits:
- Single endpoint - GraphQL is typically served over HTTP via a single endpoint, which provides access to the full set of capabilities of the service. You can issue one query to retrieve all of the data that is needed. This differs from REST APIs, which often necessitate multiple queries to multiple endpoints to retrieve the desired data. GraphQL also eliminates over- and underfetching because the structure of the data that’s returned is not fixed. Instead, it is flexible and enables the client to decide what data is needed.
- Versioning - GraphQL returns only the data that's explicitly requested, so new types and new fields on those types can be added without creating a breaking change. With REST APIs, there's limited control over the data that's returned from an endpoint. Any change can be considered a breaking change, and breaking changes require a new version.
- GraphQL explorer - Also referred to as a "GraphQL playground," this is a graphical integrated development environment (IDE) that enables you to test requests and view responses. We provide an explorer to test queries GraphQL explorer below, or you can install a third-party IDE (desktop app), such as Prisma or Insomnia, to test queries and mutations. After installing the IDE, be sure to generate your authorization token and set it as an HTTP header.
As a developer using a GraphQL API, how does using this type of API differ from using our existing formats and standards?
- The verbs are different: To retrieve data, you will issue a query, and to modify data, you will issue a mutation. (If using a client to issue queries, you can use the GET or POST method.)
- Access is the same: You will continue to issue requests over HTTP and you can continue to use clients such as cURL or Postman.
- Response format is the same: Responses are returned in JSON.
Variables
GraphQL allows you to pass variables as query arguments (referred to as "parameterizing the query"). Here's how:
In the query, replace the argument's static value with a variable, such as
$id
.Declare the variable. In the example below,
$id: String!, $idSource: IdSource
is the declaration. Each variable declaration must begin with$
and state its type. Declared variables must be scalars, enums, or input object types. Also, if the field you are passing the variable into requires a non-null argument, the variable must be required as well (as noted by the!
in the example declaration).Pass in values for the variables.
Here's an example that parameterizes the id
and idSource
arguments:
property(id: $id, idSource: $idSource) {nameunits {ids {ididSource}}}}
Here are the query variables and their values:
{"id": "695896241","idSource": "EXPEDIA"}
This way, you can pass a different variable rather than constructing an entirely new query.
Fragments and batched queries
You can create reusable bits of code called "fragments" that you can include in queries as needed. This gives you a way to avoid repeating sections of a query over and over. When you define a fragment, you provide a name and state the object to which the fields in the fragment belong.
Here is a simple example that creates the PropertyFields
fragment that retrieves fields on the Property
object:
- Instead of this:
- Do this:
Using the same concept, you can create code snippets that can be used for more complex calls. This enables you to batch queries, like this:
1{3 ...details4 units {5 ...status6 }7 }10 ...details11 units {12 ...status13 }14 }15}1617fragment details on Property {18 id19 ids {20 id21 idSource22 }23 name24}2526fragment status on Unit {27 activeStatus {28 active29 statusCheckpoint {30 name31 lastEvaluated32 resolutionStatus33 checkpoints {34 name35 path36 lastEvaluated37 resolutionStatus38 fulfilled39 }40 }41 }42}
In the response, data for listing_01 (the first query) and data for listing_02 (the second one) would be returned.
Interfaces and __typename meta field
An interface is an abstract type that includes a set of fields that multiple object types can include. If an object type implements an interface, the object type must included all of the interface's fields. This provides an easy way to define types that share the same fields.
For example, any type that implements the Guest
interface:
interface Guest {}
must include the name
and age
fields, such as shown here:
type Adult implements Guest {}type Child implements Guest {}
In addition, a field can have an interface as its return type. When querying a field that returns an interface, you can query for the interface's subfields using an inline fragment, and you can also query for subfields that aren't included in the interface. Here's a snippet that shows inline fragments (... on Adult
and ... on Child
) and also queries for workPlace
and school
, which are not fields on the interface:
query {members {name... on Adult {workPlace}... on Child {school}}}}
To help identify the actual object type (out of the possible types) that has been returned, you can include the __typename
meta field when querying against an interface. In this example, you can determine which type of family member is returned without examining the returned fields:
- Query
- Response
1query {3 __typename4 ... on Adult {5 workPlace6 }7 ... on Child {8 school9 }10 }11}
This way, if you need to handle an adult differently than a child, you don’t need to code logic based on what you request. __typename
provides the information for you.
Pagination
For queries that return large result sets, the API provides a way to paginate results (as defined by the GraphQL spec). When issuing a query, you can specify how many results are included in a page. Several fields are available to enable this functionality:
pageSize
refers to the number of results returned per page, up to 25 are allowedtotalCount
specifies the total number of resultshasNextPage
indicates that at least one more page of results is available (when set totrue
)endCursor
provides a marker for the end of the current page; this marker is specified in theafter
field in the next query request
Here is a promotions query example that sets pageSize
to 3
, which means three promotions are returned per page. The response indicates that there are 10 promotions (totalCount
) in the result set, which means that you must retrieve four pages of results. Note the values of totalCount
, hasNextPage
, and endCursor
in the response.
- Initial request
- Response
1query {2 property(id: "12345", idSource: EXPEDIA){3 promotions(pageSize: 3) {4 totalCount5 pageInfo {6 hasNextPage7 endCursor8 }9 edges {10 ...
To retrieve the next page of results, issue a request similar to the following. Take the value of endCursor
from the previous response and specify it in the after
field of the next request. Continue to issue requests and update the after
field with the value of endCursor
until the response returns "hasNextPage": false
and "endCursor": null
.
- Next request
- Next response
- Last response
1query {2 property(id: "12345", idSource: EXPEDIA){3 promotions(4 pageSize: 10,5 after: "L3Jlc2VydmF0aW9ucy9zZWFyY2gZW50aXR5Q29sbGVjdGlvbj1yZXNlcnZhdGlvbnMmcGFnZXNpemU9MiZwYWdlPTImaHlkcmF0ZT1mYWxzZSZpbm") {6 totalCount7 pageInfo {8 hasNextPage9 endCursor10 }11 edges {12 ...
GraphQL explorer
The query reference pages for GraphQL APIs provide an interactive GraphQL IDE that lets you run queries offered by the API. The explorer offers these features:
- A sample query is provided, and a test property ID is passed into the explorer; its test data is returned.
- You can execute queries in the explorer by clicking Run Query.
- Launch the full-scale explorer in another tab/window by clicking API Explorer. This explorer provides syntax highlighting, schema introspection, real-time error highlighting, and auto-completion, among other things.
- Click Graph Viewer on the full explorer to peruse the schema so you can understand object relationships.
- Click Docs on the full explorer to drill down into the schema and review field-level documentation.
- To download the schema, click Export Code and then click Download schema.zip on the dialog.
Resources
To fully understand the benefits of GraphQL, check out these learning resources: