We addressed several API types (including GraphQL) in a recent overview post. In this post, we'll look at GraphQL APIs in more detail.
A GraphQL API (application programming interface) is an API that supports GraphQL queries, mutations, and subscriptions as HTTP requests. We can collectively refer to these as operations. GraphQL APIs focus on providing (or creating) only the data which is explicitly defined in the operations.
The history of GraphQL APIs
GraphQL was originally built by Facebook in 2012 to solve performance issues tied to displaying the Facebook feed on iOS devices. Prior to this, Facebook had largely depended on REST APIs. Today, GraphQL APIs have some features from REST and RPC APIs but combined in a way unique to GraphQL.
In 2015, Facebook made GraphQL open source to demonstrate how they were tying React and GraphQL together. From that point, the number of GraphQL implementations rapidly expanded.
While a REST API is focused on allowing access to on data collections (example: customers, accounts, or invoices), a GraphQL API is more focused on the relationships which the various data elements have with each other. As a result, GraphQL queries spider through the data relationships, rather than returning entire data resources.
How GraphQL APIs work and what they are used for
GraphQL APIs use HTTP (other protocols are supported, but not used) over the web to enable integrations between apps. As with RPC APIs, GraphQL APIs have a single endpoint. Unlike an RPC API (which only supports the POST method), GraphQL APIs support both GET and POST.
However, GraphQL APIs do not support additional the full range of HTTP methods that REST APIs do. In practice, POST is used most of the time. This is due to the restrictions around the GET method which require that everything be sent as a URL query parameter, since GET requests cannot have HTML bodies.
GraphQL APIs can use any of the standard approaches to authentication, including basic auth (not recommended), API keys (common), or OAuth 2.0 (best option). However, the GraphQL specification does not explicitly address auth.
Much as SOAP APIS have the WSDL file to describe what can be done with them, GraphQL APIs have a schema. All operations are first validated against the schema before they are fulfilled.
GraphQL APIs support CRUD (create, read, update, delete) operations but they are independent of the HTTP methods. When fetching data (the R in CRUD) we send a GraphQL query to the server that describes the data we expect in return. When changing data (the C/U/D in CRUD), we issue a GraphQL mutation. We can plug variables into generic query and mutation strings by including an optional JSON string containing the variables' values.
All responses from a GraphQL query or mutation are provided in JSON as well. We can also set up subscriptions for a GraphQL API, which are essentially queries that get updated whenever there is a data change (making them analogous to webhooks).
A GraphQL operation has the following elements:
- Operation type (optional)
- Operation name (optional, unless using a variable)
- Field (required)
- Argument (optional)
- Variable (optional)
Here is a sample GraphQL query (including operation type and and name, but not argument or variable):
123456
Here is the corresponding response in JSON:
123456789101112131415161718
It's easy to parse the response because it follows the pattern defined by the request. It's entirely possible thatusers
has 20 fields (and not only the two shown), but with GraphQL, unless we explicitly ask for each of those fields in the query, they will not be returned.
Since we didn't specify any arguments to limit the response, the system returned all the values for users which had a firstName
;and lastName
. Here's what happens if we pass in an argument into the singularquery
:
123456
And here's the result:
12345678
We've used an argument to limit the scope of the request to the user having an ID of 17, and thus received only the data for user Julius Caesar.
For a sample mutation, we can add a new user record.
1234567
And we get the following response:
12345
GraphQL also provides for use of variables, aliases, fragments, and unlimited nesting of queries. However, covering all of that is beyond the scope of this overview. For more detail with reference to GraphQL queries and mutations, check out the GraphQL Queries and Mutations page.
Why SaaS teams and products use GraphQL APIs
GraphQL is one of the more recent API types for integrations. It was built specifically to restrict the amount of data returned to exactly what was requested (no under-fetching, no over-fetching) as well as to make it easier to return data for different but related objects all at once, thereby reducing the number of times we have to "go to the well" to get data. As a result, GraphQL is probably the most efficient API type for queries.
GraphQL APIs can be particularly attractive to devs because GraphQL, like SQL, includes a language for requests but at the same time describes the structure of the data being returned. GraphQL APIs are built on the concept of data as a graph that can be queried. Once you have defined the schema for a GraphQL API, you can crawl or spider through the graph to get everything needed.
What are best practices for setting up GraphQL APIs?
GraphQL APIs can be built in many different languages. Some common ones we see used are JavaScript, Ruby, Python, and TypeScript. Regardless of the language and libraries used for the GraphQL API, be sure to keep the following in mind when setting up the API and its schema.
- Use short names for operations. You could start with the verb and follow it with the action:
addUser
. Or, you could reverse the order to make it easier to scan:userAdd
. In any case, keeping names short and descriptive makes it easier for the devs who are building mutations. - Use depth and amount limiting for queries. One of the strengths of GraphQL (nested queries) can easily be used against it if too much data is requested, either in terms of the data depth or the amount of records requested. See a good article on preventing these and related issues from overwhelming your API.
- Use cost analysis for queries. Related to depth and amount limiting, in that cost analysis helps you stop unwanted queries before they execute. Here's a good overview of cost analysis for GraphQL.
- Stick with HTTP and JSON. While the GraphQL specification explicitly does not specify the transfer protocol or the transport language, HTTP and JSON are the de facto standards for implementing a GraphQL API. Instructions, examples, and everything else you need to set up your own GraphQL API are generally based on HTTP and JSON.
How do GraphQL APIs work with integrations?
When you integrate with an GraphQL API, you'll deal with the usual authentication tasks for any integration, such as handling API keys and creating OAuth 2.0 callback URLs. Once you have worked through auth, writing code for the GraphQL client is made easier by leveraging existing libraries. Many modern languages include a GraphQL client library (NodeJS has graphql-request among dozens of others).
Once you have a generic authenticated GraphQL client, your developers can send whatever queries or mutations they would like through that client. There's no need for developers to examine documentation to determine the correct endpoint to hit, or what shape of payload to expect in response – they can just ask the GraphQL server what queries and mutations it offers, and can then explicitly request the data they need.
For a refresher on APIs and integrations, check out API vs Integration: What is the Difference?
The future of GraphQL APIs
The GraphQL API spec is young, but its appeal is rapidly increasing. Postman notes that some 28% of those surveyed in 2022 use GraphQL APIs, up 4% from 2021. This, despite being only seven years old. We found GraphQL to be the right API for Prismatic, as detailed in our post.
GraphQL APIs are particularly useful for scenarios where each client is in need of different data, which can be easily specified in the individual queries. At the same time, GraphQL APIs are ideal in situations where disparate data sources are pulled together through federation (schema stitching).
For more content on GraphQL APIs and other integration topics, check out our guide to API integrations.