The GraphQL specification is edited in the markdown files found in
/spec the latest release of which is published at
https://graphql.github.io/graphql-spec/.
The latest draft specification can be found at https://graphql.github.io/graphql-spec/draft/ which tracks the latest commit to the main branch in this repository.
Previous releases of the GraphQL specification can be found at permalinks that match their release tag. For example, https://graphql.github.io/graphql-spec/October2016/. If you are linking directly to the GraphQL specification, it's best to link to a tagged permalink for the particular referenced version.
This is a Working Draft of the Specification for GraphQL, a query language for APIs created by Facebook.
The target audience for this specification is not the client developer, but those who have, or are actively interested in, building their own GraphQL implementations and tools.
In order to be broadly adopted, GraphQL will have to target a wide variety of backend environments, frameworks, and languages, which will necessitate a collaborative effort across projects and organizations. This specification serves as a point of coordination for this effort.
Looking for help? Find resources from the community.
GraphQL consists of a type system, query language and execution semantics, static validation, and type introspection, each outlined below. To guide you through each of these components, we've written an example designed to illustrate the various pieces of GraphQL.
This example is not comprehensive, but it is designed to quickly introduce the core concepts of GraphQL, to provide some context before diving into the more detailed specification or the GraphQL.js reference implementation.
The premise of the example is that we want to use GraphQL to query for information about characters and locations in the original Star Wars trilogy.
At the heart of any GraphQL implementation is a description of what types of objects it can return, described in a GraphQL type system and returned in the GraphQL Schema.
For our Star Wars example, the starWarsSchema.ts file in GraphQL.js defines this type system.
The most basic type in the system will be Human, representing characters like
Luke, Leia, and Han. All humans in our type system will have a name, so we
define the Human type to have a field called "name". This returns a String,
and we know that it is not null (since all Humans have a name), so we will
define the "name" field to be a non-nullable String. Using a shorthand notation
that we will use throughout the spec and documentation, we would describe the
human type as:
type Human {
name: String
}
This shorthand is convenient for describing the basic shape of a type system; the JavaScript implementation is more full-featured, and allows types and fields to be documented. It also sets up the mapping between the type system and the underlying data; for a test case in GraphQL.js, the underlying data is a set of JavaScript objects, but in most cases the backing data will be accessed through some service, and this type system layer will be responsible for mapping from types and fields to that service.
A common pattern in many APIs, and indeed in GraphQL is to give objects an ID that can be used to refetch the object. So let's add that to our Human type. We'll also add a string for their home planet.
type Human {
id: String
name: String
homePlanet: String
}
Since we're talking about the Star Wars trilogy, it would be useful to describe the episodes in which each character appears. To do so, we'll first define an enum, which lists the three episodes in the trilogy:
enum Episode {
NEWHOPE
EMPIRE
JEDI
}
Now we want to add a field to Human describing what episodes they were in.
This will return a list of Episodes:
type Human {
id: String
name: String
appearsIn: [Episode]
homePlanet: String
}
Now, let's introduce another type, Droid:
type Droid {
id: String
name: String
appearsIn: [Episode]
primaryFunction: String
}
Now we have two types! Let's add a way of going between them: humans and droids both have friends. But humans can be friends with both humans and droids. How do we refer to either a human or a droid?
If we look, we note that there's common functionality between humans and droids;
they both have IDs, names, and episodes in which they appear. So we'll add an
interface, Character, and make both Human and Droid implement it. Once we
have that, we can add the friends field, that returns a list of Characters.
Our type system so far is:
enum Episode {
NEWHOPE
EMPIRE
JEDI
}
interface Character {
id: String
name: String
friends: [Character]
appearsIn: [Episode]
}
type Human implements Character {
id: String
name: String
friends: [Character]
appearsIn: [Episode]
homePlanet: String
}
type Droid implements Character {
id: String
name: String
friends: [Character]
appearsIn: [Episode]
primaryFunction: String
}
One question we might ask, though, is whether any of those fields can return
null. By default, null is a permitted value for any type in GraphQL, since
fetching data to fulfill a GraphQL query often requires talking to different
services that may or may not be available. However, if the type system can
guarantee that a type is never null, then we can mark it as Non Null in the type
system. We indicate that in our shorthand by adding an "!" after the type. We
can update our type system to note that the id is never null.
Note that while in our current implementation, we can guarantee that more fields are non-null (since our current implementation has hard-coded data), we didn't mark them as non-null. One can imagine we would eventually replace our hardcoded data with a backend service, which might not be perfectly reliable; by leaving these fields as nullable, we allow ourselves the flexibility to eventually return null to indicate a backend error, while also telling the client that the error occurred.
enum Episode {
NEWHOPE
EMPIRE
JEDI
}
interface Character {
id: String!
name: String
friends: [Character]
appearsIn: [Episode]
}
type Human implements Character {
id: String!
name: String
friends: [Character]
appearsIn: [Episode]
homePlanet: String
}
type Droid implements Character {
id: String!
name: String
friends: [Character]
appearsIn: [Episode]
primaryFunction: String
}
We're missing one last piece: an entry point into the type system.
When we define a schema, we define an object type that is the basis for all
query operations. The name of this type is Query by convention, and it
describes our public, top-level API. Our Query type for this example will look
like this:
type Query {
hero(episode: Episode): Character
human(id: String!): Human
droid(id: String!): Droid
}
In this example, there are three top-level operations that can be done on our schema:
hero returns the Character who is the hero of the Star Wars trilogy; it
takes an optional argument that allows us to fetch the hero of a specific
episode instead.human accepts a non-null string as a query argument, a human's ID, and
returns the human with that ID.droid does the same for droids.These fields demonstrate another feature of the type system, the ability for a field to specify arguments that configure their behavior.
When we package the whole type system together, defining the Query type above
as our entry point for queries, this creates a GraphQL Schema.
This example just scratched the surface of the type system. The specification goes into more detail about this topic in the "Type System" section, and the type directory in GraphQL.js contains code implementing a specification-compliant GraphQL type system.
GraphQL queries declaratively describe what data the issuer wishes to fetch from whoever is fulfilling the GraphQL query.
For our Star Wars example, the starWarsQueryTests.js file in the GraphQL.js repository contains a number of queries and responses. That file is a test file that uses the schema discussed above and a set of sample data, located in starWarsData.js. This test file can be run to exercise the reference implementation.
An example query on the above schema would be:
query HeroNameQuery {
hero {
name
}
}
The initial line, query HeroNameQuery, defines a query with the operation name
HeroNameQuery that starts with the schema's root query type; in this case,
Query. As defined above, Query has a hero field that returns a
Character, so we'll query for that. Character then has a name field that
returns a String, so we query for that, completing our query. The result of
this query would then be:
{
"hero": {
"name": "R2-D2"
}
}
Specifying the query keyword and an operation name is only required when a
GraphQL document defines multiple operations. We therefore could have written
the previous query with the query shorthand:
{
hero {
name
}
}
Assuming that the backing data for the GraphQL server identified R2-D2 as the hero. The response continues to vary based on the request; if we asked for R2-D2's ID and friends with this query:
query HeroNameAndFriendsQuery {
hero {
id
name
friends {
id
name
}
}
}
then we'll get back a response like this:
{
"hero": {
"id": "2001",
"name": "R2-D2",
"friends": [
{
"id": "1000",
"name": "Luke Skywalker"
},
{
"id": "1002",
"name": "Han Solo"
},
{
"id": "1003",
"name": "Leia Organa"
}
]
}
}
One of the key aspects of GraphQL is its ability to nest queries. In the above query, we asked for R2-D2's friends, but we can ask for more information about each of those objects. So let's construct a query that asks for R2-D2's friends, gets their name and episode appearances, then asks for each of their friends.
query NestedQuery {
hero {
name
friends {
name
appearsIn
friends {
name
}
}
}
}
which will give us the nested response
{
"hero": {
"name": "R2-D2",
"friends": [
{
"name": "Luke Skywalker",
"appearsIn": ["NEWHOPE", "EMPIRE", "JEDI"],
"friends": [
{ "name": "Han Solo" },
{ "name": "Leia Organa" },
{ "name": "C-3PO" },
{ "name": "R2-D2" }
]
},
{
"name": "Han Solo",
"appearsIn": ["NEWHOPE", "EMPIRE", "JEDI"],
"friends": [
{ "name": "Luke Skywalker" },
{ "name": "Leia Organa" },
{ "name": "R2-D2" }
]
},
{
"name": "Leia Organa",
"appearsIn": ["NEWHOPE", "EMPIRE", "JEDI"],
"friends": [
{ "name": "Luke Skywalker" },
{ "name": "Han Solo" },
{ "name": "C-3PO" },
{ "name": "R2-D2" }
]
}
]
}
}
The Query type above defined a way to fetch a human given their ID. We can use
it by hard-coding the ID in the query:
query FetchLukeQuery {
human(id: "1000") {
name
}
}
to get
{
"human": {
"name": "Luke Skywalker"
}
}
Alternately, we could have defined the query to have a query parameter:
query FetchSomeIDQuery($someId: String!) {
human(id: $someId) {
name
}
}
This query is now parameterized by $someId; to run it, we must provide that
ID. If we ran it with $someId set to "1000", we would get Luke; set to "1002",
we would get Han. If we passed an invalid ID here, we would get null back for
the human, indicating that no such object exists.
Notice that the key in the response is the name of the field, by default. It is sometimes useful to change this key, for clarity or to avoid key collisions when fetching the same field with different arguments.
We can do that with field aliases, as demonstrated in this query:
query FetchLukeAliased {
luke: human(id: "1000") {
name
}
}
We aliased the result of the human field to the key luke. Now the response
is:
{
"luke": {
"name": "Luke Skywalker"
}
}
Notice the key is "luke" and not "human", as it was in our previous example where we did not use the alias.
This is particularly useful if we want to use the same field twice with different arguments, as in the following query:
query FetchLukeAndLeiaAliased {
luke: human(id: "1000") {
name
}
leia: human(id: "1003") {
name
}
}
We aliased the result of the first human field to the key luke, and the
second to leia. So the result will be:
{
"luke": {
"name": "Luke Skywalker"
},
"leia": {
"name": "Leia Organa"
}
}
Now imagine we wanted to ask for Luke and Leia's home planets. We could do so with this query:
```graphql query DuplicateFields { luke: human(id: "1000") { name homePlanet } leia: h
$ claude mcp add graphql-spec \
-- python -m otcore.mcp_server <graph>