TL;DR version
In one of the previous posts, we discussed, in brief, what’s it like to use the GitHub API v3. This version is designed to be interfaced like any other REST API. There are endpoints for every resource that you need to access and/or modify. There are endpoints for each user, each organization, each repository and so on. For example, each user has his/her API endpoint at https://api.github.com/users/<username> you can try substituting your username instead of <username> and enter the URL in a browser to see what the API responds with.
GitHub API v4, on the other hand, uses GraphQL where the QL stands for Query Language. GraphQL is a new way of designing your APIs. Just like there are many web services offered as REST APIs not just the ones offered by GitHub, there are many web services that allows you to interface with them via GraphQL.
The starkest difference you will notice between GraphQL and REST API is that GraphQL can work off of a single API endpoint. In case of GitHub API v4, this end point is https://api.github.com/graphql and that’s that. You don’t have to worry about appending long strings at the end of a root URI or supply a query string parameter for extra information. You simply send a JSON like argument to this API, asking only for the things you need, and you will get a JSON payload back with the exact same information that you requested. You don’t have to deal with filtering out unwanted informations, or suffer from performance overhead because of large responses.
What is REST API?
Well, REST stands for Representational State Transfer and API stands for Application Programming Interface. A REST API, or a ‘RESTful’ API, has become the core design-philosophy behind most modern client-server applications. The idea emerges from the need to segregate various the components of an application like the client-side UI and server-side logic.
So the session between a client and a server is typically stateless. Once the webpage and related scripts are loaded you can continue to interact with them and when you perform an action (like press a send button) then a send request is sent along with all the contextual information that the web server needs to process that request (like username, tokens, etc). The application transitions from one state to another but without a constant need for connection between the client and the server.
REST defines a set of constraints between the client and the server, and the communication can only happen under those constraints. For example REST over HTTP usually uses the CRUD model, which stands for Create, Read, Update and Delete and HTTP methods like POST, GET, PUT and DELETE help you perform those operations and those operations alone. Old intrusion techniques like SQL injections are not a possibility with something like a tightly written REST API(although it is REST is not a security panacea).
It also helps UI developers quite a lot! Since all you recieve from an HTTP request is typical a stream of text (formatted as JSON, sometimes) you can easily implement a web page for browsers or an app (in your preferred language) without worrying about server side architecture. You read the API documentation for services like Reddit, Twitter or Facebook and you can write extensions for them or third-party clients in the language of your choice since you are guaranteed that the behaviour of the API will still be the same.
Conversely, the server doesn’t care whether the front-end is written in Go, Ruby or Python. Whether it is a browser, app or a CLI. It just ‘sees’ the request and responds appropriately.
What is GraphQL?
As with anything in the world of computers, REST APIs got larger and more complex and at the same time people wanted to implement and consume them in a faster and simpler manner. This is why Facebook came up with the idea of GraphQL, and later open sourced it. The QL in GraphQL stands for Query Language.
GraphQL allows clients to make very specific API requests, instead of making rigid API calls with predefined parameters and responses. It is much more simpler because the server then responds with exactly the data that you asked it for, with nothing excess.
Take a look at this REST request and its corresponding response. This request is meant to view just a user’s public bio.
Response:
{
"login": "octocat",
"id": 583231,
"node_id": "MDQ6VXNlcjU4MzIzMQ==",
"avatar_url": "https://avatars3.githubusercontent.com/u/583231?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/octocat",
"html_url": "https://github.com/octocat",
"followers_url": "https://api.github.com/users/octocat/followers",
"following_url": "https://api.github.com/users/octocat/following{/other_user}",
"gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
"starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
"organizations_url": "https://api.github.com/users/octocat/orgs",
"repos_url": "https://api.github.com/users/octocat/repos",
"events_url": "https://api.github.com/users/octocat/events{/privacy}",
"received_events_url": "https://api.github.com/users/octocat/received_events",
"type": "User",
"site_admin": false,
"name": "The Octocat",
"company": "GitHub",
"blog": "http://www.github.com/blog",
"location": "San Francisco",
"email": null,
"hireable": null,
"bio": null,
"public_repos": 8,
"public_gists": 8,
"followers": 2455,
"following": 9,
"created_at": "2011-01-25T18:44:36Z",
"updated_at": "2018-11-22T16:00:23Z"
}
I have used the username octocat, but you can replace it with the username of your choice and use cURL to make this request in the command-line or Postman if you require a GUI. While the request was simple, think about all the extra information you are getting from this response. If you were to process data from a million such users and filter out all the unnecessary data using then that is not efficient. You are wasting bandwidth, memory and compute in getting, storing and filtering away all the millions extra key-value pairs that you will never you
Also the structure of the response is not something you know beforehand. This JSON response is equivalent to dictionary object in Python, or an object in JavaScript. Other endpoints will respond with JSON objects that may be composed of nested objects, nested list within the object or any arbitrary combination of JSON data types, and you will need to refer the documentation to get the specifics. When you are processing the request, you need to be cognizant of this format which change from endpoint to endpoint.
GraphQL doesn’t rely on HTTP verbs like POST, GET, PUT and DELETE to perform CRUD operations on the server. Instead, there is only one type of HTTP request type and endopint for all CRUD related operations. In case of GitHub this involves requests of type POST with only one endpoint https://api.github.com/graphql
Being a POST request it can carry with it a JSON like body of text through which will be our GraphQL operations. These operations can be of typea query if all it wants to do is read some information, or it can be a mutation in case data needs to be modified.
To make GraphQL API calls you can use GitHub’s GraphQL explorer. Take a look at this GraphQL query to fetch the same kind of data (a user’s public bio ) as we did above using REST.
query{
user (login: "ranvo") {
bio
}
}
Response:
{
"data": {
"user": {
"bio": "Tech and science enthusiasts. I am into all sorts of unrelated stuff from
servers to quantum physics.rnOccasionally, I write blog posts on the above interests."
}
}
}
As you can see, the response consists of only what you asked for, that’s the user’s bio. You select a specific user by passing the username (in my case, it’s ranvo) and then you ask for the value of an attribute of that user, in this case that attribute is bio. The API server looks up the exact specific information and responds with that and nothing else.
On the flip side, GraphQL also let’s you make a single request and extract information that would have taken you multiple requests in traditional REST API. Recall that all GraphQL requests are made to only one API endpoint. Take for example the use case where you need to ask the GitHub API server for user’s bio and one of its SSH keys. It would require two GET resquests.
GET https://api.github.com/<username>/keys
GraphQL request: POST https://api.github.com/graphql/
query{
user (login: "ranvo") {
bio
publicKeys (last:1){
edges {
node {
key
}
}
}
}
}
GraphQL Response:
{
"data": {
"user": {
"bio": "Tech and science enthusiasts. I am into all sorts of unrelated stuff from
servers to quantum physics.rnOccasionally, I write blog posts on the above interests.",
"publicKeys": {
"edges": [
{
"node": {
"key": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH31mVjRYdzeh8oD8jvaFpRuIgL65SwILyKpeGBUNGOT"
}
}
]
}
}
}
}
There are nested object, but if you look at your request, they pretty much match your request so you can know and, in some sense, shape the structure of the response you get .
Conclusion
GraphQL does come with its own learning curve, which is very steep, or not steep at all depending on who it is that you are asking. From an objective standpoint, I can lay the following facts for you. It is flexible as you have seen above, it is introspective — that is to say, you can query the GraphQL API about the API itself. Even if you are not going to build your API server using it, chances are you will have to interface with an API that does allows only GraphQL.
You can learn a bit more about its technicalities here and if you want to make GraphQL API calls from you local workstation then use Graphiql.