Odyssey

Intro to GraphQL with TypeScript & Apollo Server

Course overview and setupGraphQL basicsSchema definition language (SDL)Building the schemaApollo ServerApollo Sandbox ExplorerThe listings REST APIResolversCodegenQuerying real dataQuery argumentsAdding the Amenity typeResolver chainsMutations
14. Mutations
7m

Overview

We've seen the power of specific and expressive queries that let us retrieve exactly the data we're looking for, all at once. But querying in GraphQL is just one part of the equation.

When we want to actually change, insert, or delete data, we need to reach for a new tool: GraphQL mutations.

In this lesson, we will:

  • Explore mutation syntax and write an operation to create a new listing
  • Learn about GraphQL input types
  • Learn about mutation response best practices

Mutations in Airlock

Onward to the next feature in our Airlock API: creating a new listing.

A mockup showing a view that lets us create a new listing by specifying its pertinent properties

Our REST API comes equipped with an endpoint that allows us to create new listings: POST /listings.

This method accepts a listing property on our request body. It should contain all of the properties relevant to the listing, including its amenities. Once the listing has been created in the database, this endpoint returns the newly-created listing to us.

All right, now how do we enable this functionality in GraphQL?

Designing mutations

Much like the Query type, the Mutation type serves as an entry point to our schema. It follows the same syntax as the schema definition language, or SDL, that we've been using so far.

We declare the Mutation type using the type keyword, then the name Mutation. Inside the curly braces, we have our entry points, the fields we'll be using to mutate our data.

Let's open up schema.graphql and add a new Mutation type.

schema.graphql
type Mutation {
}

For the fields of the Mutation, we recommend starting with a verb that describes the specific action of our update operation (such as add, delete, or create), followed by whatever data the mutation acts on.

We'll explore how we can create a new listing, so we'll call this mutation createListing.

type Mutation {
"Creates a new listing"
createListing: #TODO
}

For the return type of the createListing mutation, we could return the Listing type; it's the object type we want the mutation to act upon. However, we recommend following a consistent Response type for mutation responses. Let's see what this looks like in a new type.

The Mutation response type

Return types for Mutation fields usually start with the name of the mutation, followed by Payload or Response. Don't forget that type names should be formatted in PascalCase!

Following convention, we'll name our type CreateListingResponse.

type CreateListingResponse {
}

We should return the object type that we're mutating (Listing, in our case), so that clients have access to the updated object.

type CreateListingResponse {
listing: Listing
}

Note: Though our mutation acts upon a single Listing object, it's also possible for a mutation to change and return multiple objects at once.

Notice that the listing field returns a Listing type that can be null, because our mutation might fail.

To account for any partial errors that might occur and return helpful information to the client, there are a few additional fields we can include in a response type.

  • code: an Int that refers to the status of the response, similar to an HTTP status code.

  • success: a Boolean flag that indicates whether all the updates the mutation was responsible for succeeded.

  • message: a String to display information about the result of the mutation on the client side. This is particularly useful if the mutation was only partially successful and a generic error message can't tell the whole story.

Let's also add comments for each of these fields so that it makes our GraphQL API documentation more useful.

type CreateListingResponse {
"Similar to HTTP status code, represents the status of the mutation"
code: Int!
"Indicates whether the mutation was successful"
success: Boolean!
"Human-readable message for the UI"
message: String!
"The newly created listing"
listing: Listing
}

Lastly, we can set the return type of our mutation to this new CreateListingResponse type, and make it non-nullable. Here's what the createListing mutation should look like now:

type Mutation {
"Creates a new listing"
createListing: CreateListingResponse!
}

The Mutation input

To create a new listing, our mutation needs to receive some input.

Let's think about the kind of input this createListing mutation would expect. We need all of the details about the listing itself, such as title, costPerNight, numOfBeds, amenities and so on.

We've used a GraphQL argument before in the Query.listing field: we passed in a single argument called id.

type Query {
listing(id: ID!): Listing
}

But createListing takes more than one argument. One way we could tackle this is to add each argument, one-by-one, to our createListing mutation. But this approach can become unwieldy and hard to understand. Instead, it's a good practice to use GraphQL input types as arguments for a field.

Exploring the input type

The input type in a GraphQL schema is a special object type that groups a set of arguments together, and can then be used as an argument to another field. Using input types helps us group and understand arguments, especially for mutations.

To define an input type, use the input keyword followed by the name and curly braces ({}). Inside the curly braces, we list the fields and types as usual. Note that fields of an input type can be only a scalar, an enum, or another input type.

input CreateListingInput {
}

Next, we'll add properties. To flesh out the listing we're about to create, let's send all the relevant details. We'll need: title, description, numOfBeds, costPerNight, and closedForBookings.

input CreateListingInput {
"The listing's title"
title: String!
"The listing's description"
description: String!
"The number of beds available"
numOfBeds: Int!
"The cost per night"
costPerNight: Float!
"Indicates whether listing is closed for bookings (on hiatus)"
closedForBookings: Boolean
}

We also need to specify the amenities our listing has to offer. Notice that the amenity options in our mock-up for creating a new listing are pre-defined; we can only select from existing options. Behind the scenes, each of these amenities has a unique ID identifier. For this reason, we'll add an amenities field to CreateListingInput with a type of [ID!]!.

input CreateListingInput {
"The listing's title"
title: String!
"The listing's description"
description: String!
"The number of beds available"
numOfBeds: Int!
"The cost per night"
costPerNight: Float!
"Indicates whether listing is closed for bookings (on hiatus)"
closedForBookings: Boolean
"The Listing's amenities"
amenities: [ID!]!
}

Note: You can learn more about the input type, as well as other GraphQL types and features in Side Quest: Intermediate Schema Design.

Using the input

To use an input type in the schema, we can set it as the type of a field argument. For example, we can update the createListing mutation to use CreateListingInput type like so:

type Mutation {
"Creates a new listing"
createListing(input: CreateListingInput!): CreateListingResponse!
}

Notice that the CreateListingInput is non-nullable. To run this mutation, we actually need to require some input!

type Mutation {
"Creates a new listing"
createListing(input: CreateListingInput!): CreateListingResponse!
}
input CreateListingInput {
"The listing's title"
title: String!
"The listing's description"
description: String!
"The number of beds available"
numOfBeds: Int!
"The cost per night"
costPerNight: Float!
"Indicates whether listing is closed for bookings (on hiatus)"
closedForBookings: Boolean
"The Listing's amenities"
amenities: [ID!]!
}
type CreateListingResponse {
"Similar to HTTP status code, represents the status of the mutation"
code: Int!
"Indicates whether the mutation was successful"
success: Boolean!
"Human-readable message for the UI"
message: String!
"The newly created listing"
listing: Listing
}

Building the ListingAPI method

As we've done for other requests, we'll build a method to manage this REST API call to create a new listing.

Back in datasources/listing-api.ts, let's add a new method for this mutation.

datasources/listing-api.ts
createListing() {
// TODO
}

This time, because the endpoint uses the POST method, we'll use the this.post helper method from RESTDataSource instead of this.get.

Next, we'll pass our endpoint to this method: "listings"

listing-api.ts
createListing() {
return this.post("listings");
}

Our method will receive a new listing argument, which is of type CreateListingInput. We can import this type from types.ts.

import { Amenity, Listing, CreateListingInput } from "../types";

Then let's update the createListing method to receive the new listing.

createListing(listing: CreateListingInput) {
// method logic
}

We can pass a second argument to the this.post method to specify a request body. Let's add those curly braces now, and specify a property called body, which is another object.

listing-api.ts
createListing(listing: CreateListingInput) {
return this.post("listings", {
body: {}
});
}

Inside of this object, we'll pass our listing.

return this.post("listings", {
body: { listing },
});

Note: We're using shorthand property notation with implied keys, because we've named our constant with the matching key (listing).

Now we can take care of our method's return type. When the listing is created successfully, this endpoint will return a Promise that resolves to the newly-created listing object. So we can annotate our method with a return type of Promise<Listing>.

createListing(listing: CreateListingInput): Promise<Listing> {
return this.post("listings", {
body: {
listing
}
});
}

And finally: we can clarify the type of data the this.post call will return by passing in Listing as a type variable. This keeps our method annotations super clear! We know what kind of data we can expect from calling each of our REST API's endpoints.

return this.post<Listing>("listings", {
body: {
listing,
},
});

Now let's finish up with our resolver function!

import { RESTDataSource } from "@apollo/datasource-rest";
import { Listing, Amenity, CreateListingInput } from "../types";
export class ListingAPI extends RESTDataSource {
baseURL = "https://rt-airlock-services-listing.herokuapp.com/";
getFeaturedListings(): Promise<Listing[]> {
return this.get<Listing[]>("featured-listings");
}
getListing(listingId: string): Promise<Listing> {
return this.get<Listing>(`listings/${listingId}`);
}
getAmenities(listingId: string): Promise<Amenity[]> {
return this.get<Amenity[]>(`listings/${listingId}/amenities`);
}
createListing(listing: CreateListingInput): Promise<Listing> {
return this.post<Listing>("listings", {
body: { listing }
});
}
}

Connecting the dots in our resolver

Jump back into the resolvers.ts file. We'll add a new entry to our resolvers object called Mutation.

resolvers.ts
Mutation: {
// TODO
},

Let's add our createListing resolver.

resolvers.ts
Mutation: {
createListing: (parent, args, contextValue, info) => {
// TODO
}
},

We won't need the parent or info parameters here, so we'll replace parent with _ and remove info altogether.

resolvers.ts
createListing: (_, args, contextValue) => {
// TODO
},

We know from our Mutation.createListing schema field that this resolver will receive an argument called input. We'll destructure args for this property. And while we're here, we'll also destructure contextValue for the dataSources property.

resolvers.ts
createListing: (_, { input }, { dataSources }) => {
// TODO
},

Now we'll call the createListing method from the listingAPI data source, passing it our input.

resolvers.ts
createListing: (_, { input }, { dataSources }) => {
dataSources.listingAPI.createListing(input);
},

We're not returning anything from this method just yet, so we might see some errors. In our schema we specified that the Mutation.createListing field should return a CreateListingResponse type.

schema.graphql
type CreateListingResponse {
"Similar to HTTP status code, represents the status of the mutation"
code: Int!
"Indicates whether the mutation was successful"
success: Boolean!
"Human-readable message for the UI"
message: String!
"The newly created listing"
listing: Listing
}

This means that the object we return from our resolver needs to match this shape. Let's start by setting up the object that we'll return in the event that our mutation operation succeeds.

resolvers.ts
createListing: (_, { input }, { dataSources }) => {
dataSources.listingAPI.createListing(input);
// everything succeeds with the mutation
return {
code: 200,
success: true,
message: "Listing successfully created!",
listing: null, // We don't have this value yet
}
},

Checking the response

Now, let's take a look at the response from our API call. We'll need to make our entire resolver async in order to await the results of calling dataSources.listingAPI.createListing().

resolvers.ts
createListing: async (_, { input }, { dataSources }) => {
const response = await dataSources.listingAPI.createListing(input);
console.log(response);
// everything succeeds with the mutation
return {
code: 200,
success: true,
message: "Listing successfully created!",
listing: null, // We don't have this value yet
}
},

In Sandbox, let's put together a mutation operation.

mutation CreateListing($input: CreateListingInput!) {
createListing(input: $input) {
code
success
message
}
}

And add the following to the Variables panel.

{
"input": {
"title": "Mars' top destination",
"description": "A really cool place to stay",
"costPerNight": 44.0,
"amenities": ["am-1", "am-2"],
"numOfBeds": 2
}
}

When we run the operation, we'll see that this mutation actually works as expected! We can clearly see the values we set for code, success, and message in our happy path.

{
"data": {
"createListing": {
"code": 200,
"success": true,
"message": "Listing successfully created!"
}
}
}

And in the terminal of our running server, we'll see the response from the API logged out: it's our newly-created listing!

{
id: '22ff64fe-41d4-4754-acbb-22ac89e27620',
title: "Mars' top destination",
description: 'A really cool place to stay',
costPerNight: 44,
hostId: null,
locationType: null,
numOfBeds: 2,
photoThumbnail: null,
isFeatured: null,
latitude: null,
longitude: null,
closedForBookings: null,
amenities: [
{
id: 'am-1',
category: 'Accommodation Details',
name: 'Interdimensional wifi'
},
{ id: 'am-2', category: 'Accommodation Details', name: 'Towel' }
]
}

This means we can return the whole value of the response as the listing property in the object we return.

return {
code: 200,
success: true,
message: "Listing successfully created!",
listing: response,
};

Now let's build out the sad path—when our mutation doesn't go as expected.

Handling the sad path

Returning to our Mutation.createListing resolver, we'll account for the error state.

We'll start by wrapping everything we've written so far in a try/catch block.

resolvers.ts
try {
const response = await dataSources.listingAPI.createListing(input);
return {
code: 200,
success: true,
message: "Listing successfully created!",
listing: response,
};
} catch (err) {}

Inside of the catch block, we'll return an object with some different properties.

resolvers.ts
try {
// try block body
} catch (err) {
return {
code: 500,
success: false,
message: `Something went wrong: ${err.extensions.response.body}`,
listing: null,
};
}

Here's how your entire resolver function should look.

Mutation: {
createListing: async (_, { input }, { dataSources }) => {
try {
const response = await dataSources.listingAPI.createListing(input);
return {
code: 200,
success: true,
message: "Listing successfully created!",
listing: response
};
} catch (err) {
return {
code: 500,
success: false,
message: `Something went wrong: ${err.extensions.response.body}`,
listing: null
};
}
},
},

To test our sad path, let's try creating a listing with a non-existent amenity ID.

Back in Sandbox, let's update our operation to include more information about the listing we'll attempt to create.

A mutation, doomed to fail
mutation CreateListing($input: CreateListingInput!) {
createListing(input: $input) {
code
success
message
listing {
title
description
costPerNight
amenities {
name
category
}
}
}
}

Then let's update our Variables panel; this time, we'll update our listing's "numOfBeds" to be zero.

{
"input": {
"title": "Mars' top destination",
"description": "A really cool place to stay",
"costPerNight": 44.0,
"amenities": ["am-1", "am-2"],
"numOfBeds": 0
}
}

When we run the operation, we'll see the values we expect: the mutation failed, and our error message comes through loud and clear. Something went wrong: Please provide a valid number of beds!

{
"data": {
"createListing": {
"code": 500,
"success": false,
"message": "Something went wrong: Please provide a valid number of beds",
"listing": null
}
}
}

With our sad path validated, let's revert our change to the Variables panel—we need at least one bed available at our listing!

{
"input": {
"title": "Mars' top destination",
"description": "A really cool place to stay",
"costPerNight": 44.0,
"amenities": ["am-1", "am-2"],
"numOfBeds": 2
}
}

Now let's run that mutation one more time and see if all of our listing data is accounted for.

A mutation, presumed to succeed
mutation CreateListing($input: CreateListingInput!) {
createListing(input: $input) {
code
success
message
listing {
title
description
costPerNight
amenities {
name
category
}
}
}
}

Run the query and... data!

{
"data": {
"createListing": {
"code": 200,
"success": true,
"message": "Listing successfully created!",
"listing": {
"title": "Mars' top destination",
"description": "A really cool place to stay",
"costPerNight": 44,
"amenities": [
{
"name": "Interdimensional wifi",
"category": "Accommodation Details"
},
{
"name": "Towel",
"category": "Accommodation Details"
}
]
}
}
}
}

Bravo, you've done it!

Practice

Which of these are good names for mutations based on the recommended conventions above?
In the mutation response type (CreateListingResponse), why is the modified object's return type (Listing) nullable?
How can we use the input type in our schema?
When creating an input type for a mutation, what naming convention is commonly used?
Code Challenge!

Update Mutation.createPlanet to accept an input of type non-null CreatePlanetInput and return a non-null CreatePlanetResponse type. Next, complete CreatePlanetInput with name and mass fields. (See the Planet type for reference!)

Key takeaways

  • Mutations are write operations used to modify data.
  • Naming mutations usually starts with a verb that describes the action, such as "add," "delete," or "create."
  • It's a common convention to create a consistent response type for mutation responses.
  • Mutations in GraphQL often require multiple arguments to perform actions. To group arguments together, we use a GraphQL input type for clarity and maintainability.

Journey's end

Task!

You've built a GraphQL API! You've got a working GraphQL server, jam-packed with intergalactic listings, that uses a REST API as a data source. You've written queries and mutations, and learned some common GraphQL conventions along the way. You've explored how to use GraphQL arguments, variables, and input types in your schema design. Take a moment to celebrate; that's a lot of learning!

But the journey doesn't end here! When you're ready to take your GraphQL API even further, jump into the next course in this series: Federation with TypeScript & Apollo Server.

Thanks for joining us in this course; we hope to see you in the next one!

Previous

Share your questions and comments about this lesson

Your feedback helps us improve! If you're stuck or confused, let us know and we'll help you out. All comments are public and must follow the Apollo Code of Conduct. Note that comments that have been resolved or addressed may be removed.

You'll need a GitHub account to post below. Don't have one? Post in our Odyssey forum instead.

              querying

              A request for specific data from a GraphQL server. Clients define the structure of the response, enabling precise and efficient data retrieval.

              GraphQL

              An open-source query language and specification for APIs that enables clients to request specific data, promoting efficiency and flexibility in data retrieval.

              GraphQL

              An open-source query language and specification for APIs that enables clients to request specific data, promoting efficiency and flexibility in data retrieval.

              mutations

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              mutation

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              operation

              A single query, mutation, or subscription that clients send to a GraphQL server to request or manipulate data.

              GraphQL

              An open-source query language and specification for APIs that enables clients to request specific data, promoting efficiency and flexibility in data retrieval.

              mutation

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              GraphQL

              An open-source query language and specification for APIs that enables clients to request specific data, promoting efficiency and flexibility in data retrieval.

              schema definition language

              GraphQL's schema definition language (SDL). The syntax for writing GraphQL schemas. All GraphQL APIs can use SDL to represent their schema, regardless of the API's programming language.

              SDL

              GraphQL's schema definition language (SDL). The syntax for writing GraphQL schemas. All GraphQL APIs can use SDL to represent their schema, regardless of the API's programming language.

              fields

              A unit of data that belongs to a type in a schema. Every GraphQL query requests one or more fields.

              type Author {
              # id, firstName, and lastName are all fields of the Author type
              id: Int!
              firstName: String
              lastName: String
              }
              fields

              A unit of data that belongs to a type in a schema. Every GraphQL query requests one or more fields.

              type Author {
              # id, firstName, and lastName are all fields of the Author type
              id: Int!
              firstName: String
              lastName: String
              }
              operation

              A single query, mutation, or subscription that clients send to a GraphQL server to request or manipulate data.

              mutation

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              mutation

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              mutation

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              object type

              A type in a GraphQL schema that has one or more fields. User is an object type in the following example:

              type User {
              name: String!
              }
              mutation

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              mutation

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              fields

              A unit of data that belongs to a type in a schema. Every GraphQL query requests one or more fields.

              type Author {
              # id, firstName, and lastName are all fields of the Author type
              id: Int!
              firstName: String
              lastName: String
              }
              mutation

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              object type

              A type in a GraphQL schema that has one or more fields. User is an object type in the following example:

              type User {
              name: String!
              }
              mutation

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              mutation

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              field

              A unit of data that belongs to a type in a schema. Every GraphQL query requests one or more fields.

              type Author {
              # id, firstName, and lastName are all fields of the Author type
              id: Int!
              firstName: String
              lastName: String
              }
              mutation

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              fields

              A unit of data that belongs to a type in a schema. Every GraphQL query requests one or more fields.

              type Author {
              # id, firstName, and lastName are all fields of the Author type
              id: Int!
              firstName: String
              lastName: String
              }
              mutation

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              mutation

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              fields

              A unit of data that belongs to a type in a schema. Every GraphQL query requests one or more fields.

              type Author {
              # id, firstName, and lastName are all fields of the Author type
              id: Int!
              firstName: String
              lastName: String
              }
              GraphQL

              An open-source query language and specification for APIs that enables clients to request specific data, promoting efficiency and flexibility in data retrieval.

              mutation

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              mutation

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              mutation

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              mutation

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              GraphQL

              An open-source query language and specification for APIs that enables clients to request specific data, promoting efficiency and flexibility in data retrieval.

              argument

              A key-value pair associated with a particular schema field that lets operations pass data to that field's resolver.

              Argument values can be hardcoded as literal values (shown below for clarity) or provided via GraphQL variables (recommended).

              query GetHuman {
              human(id: "200") {
              name
              height(unit: "meters")
              }
              }
              field

              A unit of data that belongs to a type in a schema. Every GraphQL query requests one or more fields.

              type Author {
              # id, firstName, and lastName are all fields of the Author type
              id: Int!
              firstName: String
              lastName: String
              }
              argument

              A key-value pair associated with a particular schema field that lets operations pass data to that field's resolver.

              Argument values can be hardcoded as literal values (shown below for clarity) or provided via GraphQL variables (recommended).

              query GetHuman {
              human(id: "200") {
              name
              height(unit: "meters")
              }
              }
              argument

              A key-value pair associated with a particular schema field that lets operations pass data to that field's resolver.

              Argument values can be hardcoded as literal values (shown below for clarity) or provided via GraphQL variables (recommended).

              query GetHuman {
              human(id: "200") {
              name
              height(unit: "meters")
              }
              }
              mutation

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              GraphQL

              An open-source query language and specification for APIs that enables clients to request specific data, promoting efficiency and flexibility in data retrieval.

              arguments

              A key-value pair associated with a particular schema field that lets operations pass data to that field's resolver.

              Argument values can be hardcoded as literal values (shown below for clarity) or provided via GraphQL variables (recommended).

              query GetHuman {
              human(id: "200") {
              name
              height(unit: "meters")
              }
              }
              field

              A unit of data that belongs to a type in a schema. Every GraphQL query requests one or more fields.

              type Author {
              # id, firstName, and lastName are all fields of the Author type
              id: Int!
              firstName: String
              lastName: String
              }
              GraphQL schema

              A GraphQL schema defines the structure and types of data that can be queried or mutated, serving as a contract between the server and clients.

              object type

              A type in a GraphQL schema that has one or more fields. User is an object type in the following example:

              type User {
              name: String!
              }
              arguments

              A key-value pair associated with a particular schema field that lets operations pass data to that field's resolver.

              Argument values can be hardcoded as literal values (shown below for clarity) or provided via GraphQL variables (recommended).

              query GetHuman {
              human(id: "200") {
              name
              height(unit: "meters")
              }
              }
              field

              A unit of data that belongs to a type in a schema. Every GraphQL query requests one or more fields.

              type Author {
              # id, firstName, and lastName are all fields of the Author type
              id: Int!
              firstName: String
              lastName: String
              }
              arguments

              A key-value pair associated with a particular schema field that lets operations pass data to that field's resolver.

              Argument values can be hardcoded as literal values (shown below for clarity) or provided via GraphQL variables (recommended).

              query GetHuman {
              human(id: "200") {
              name
              height(unit: "meters")
              }
              }
              mutations

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              fields

              A unit of data that belongs to a type in a schema. Every GraphQL query requests one or more fields.

              type Author {
              # id, firstName, and lastName are all fields of the Author type
              id: Int!
              firstName: String
              lastName: String
              }
              scalar

              A "base" type that resolves to a single value. GraphQL includes the following scalar types by default: Int, Float, String, Boolean, and ID.

              field

              A unit of data that belongs to a type in a schema. Every GraphQL query requests one or more fields.

              type Author {
              # id, firstName, and lastName are all fields of the Author type
              id: Int!
              firstName: String
              lastName: String
              }
              GraphQL

              An open-source query language and specification for APIs that enables clients to request specific data, promoting efficiency and flexibility in data retrieval.

              field

              A unit of data that belongs to a type in a schema. Every GraphQL query requests one or more fields.

              type Author {
              # id, firstName, and lastName are all fields of the Author type
              id: Int!
              firstName: String
              lastName: String
              }
              argument

              A key-value pair associated with a particular schema field that lets operations pass data to that field's resolver.

              Argument values can be hardcoded as literal values (shown below for clarity) or provided via GraphQL variables (recommended).

              query GetHuman {
              human(id: "200") {
              name
              height(unit: "meters")
              }
              }
              mutation

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              mutation

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              mutation

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              argument

              A key-value pair associated with a particular schema field that lets operations pass data to that field's resolver.

              Argument values can be hardcoded as literal values (shown below for clarity) or provided via GraphQL variables (recommended).

              query GetHuman {
              human(id: "200") {
              name
              height(unit: "meters")
              }
              }
              argument

              A key-value pair associated with a particular schema field that lets operations pass data to that field's resolver.

              Argument values can be hardcoded as literal values (shown below for clarity) or provided via GraphQL variables (recommended).

              query GetHuman {
              human(id: "200") {
              name
              height(unit: "meters")
              }
              }
              variable

              A placeholder for dynamic values in an operation allowing parameterization and reusability in requests. Variables can be used to fill arguments or passed to directives.

              query GetUser($userId: ID!) {
              user(id: $userId) {
              firstName
              }
              }

              In the query above, userId is a variable. The variable and its type are declared in the operation signature, signified by a $. The type of variable is a non-nullable ID. A variable's type must match the type of any argument it's used for.

              resolver

              A function that populates data for a particular field in a GraphQL schema. For example:

              const resolvers = {
              Query: {
              author(root, args, context, info) {
              return find(authors, { id: args.id });
              },
              },
              };
              resolver

              A function that populates data for a particular field in a GraphQL schema. For example:

              const resolvers = {
              Query: {
              author(root, args, context, info) {
              return find(authors, { id: args.id });
              },
              },
              };
              field

              A unit of data that belongs to a type in a schema. Every GraphQL query requests one or more fields.

              type Author {
              # id, firstName, and lastName are all fields of the Author type
              id: Int!
              firstName: String
              lastName: String
              }
              resolver

              A function that populates data for a particular field in a GraphQL schema. For example:

              const resolvers = {
              Query: {
              author(root, args, context, info) {
              return find(authors, { id: args.id });
              },
              },
              };
              argument

              A key-value pair associated with a particular schema field that lets operations pass data to that field's resolver.

              Argument values can be hardcoded as literal values (shown below for clarity) or provided via GraphQL variables (recommended).

              query GetHuman {
              human(id: "200") {
              name
              height(unit: "meters")
              }
              }
              field

              A unit of data that belongs to a type in a schema. Every GraphQL query requests one or more fields.

              type Author {
              # id, firstName, and lastName are all fields of the Author type
              id: Int!
              firstName: String
              lastName: String
              }
              resolver

              A function that populates data for a particular field in a GraphQL schema. For example:

              const resolvers = {
              Query: {
              author(root, args, context, info) {
              return find(authors, { id: args.id });
              },
              },
              };
              mutation

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              operation

              A single query, mutation, or subscription that clients send to a GraphQL server to request or manipulate data.

              resolver

              A function that populates data for a particular field in a GraphQL schema. For example:

              const resolvers = {
              Query: {
              author(root, args, context, info) {
              return find(authors, { id: args.id });
              },
              },
              };
              mutation

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              operation

              A single query, mutation, or subscription that clients send to a GraphQL server to request or manipulate data.

              operation

              A single query, mutation, or subscription that clients send to a GraphQL server to request or manipulate data.

              mutation

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              mutation

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              resolver

              A function that populates data for a particular field in a GraphQL schema. For example:

              const resolvers = {
              Query: {
              author(root, args, context, info) {
              return find(authors, { id: args.id });
              },
              },
              };
              resolver

              A function that populates data for a particular field in a GraphQL schema. For example:

              const resolvers = {
              Query: {
              author(root, args, context, info) {
              return find(authors, { id: args.id });
              },
              },
              };
              operation

              A single query, mutation, or subscription that clients send to a GraphQL server to request or manipulate data.

              operation

              A single query, mutation, or subscription that clients send to a GraphQL server to request or manipulate data.

              mutation

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              mutation

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              query

              A request for specific data from a GraphQL server. Clients define the structure of the response, enabling precise and efficient data retrieval.

              Mutations

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              operations

              A single query, mutation, or subscription that clients send to a GraphQL server to request or manipulate data.

              mutations

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              mutation

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              Mutations

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              GraphQL

              An open-source query language and specification for APIs that enables clients to request specific data, promoting efficiency and flexibility in data retrieval.

              arguments

              A key-value pair associated with a particular schema field that lets operations pass data to that field's resolver.

              Argument values can be hardcoded as literal values (shown below for clarity) or provided via GraphQL variables (recommended).

              query GetHuman {
              human(id: "200") {
              name
              height(unit: "meters")
              }
              }
              GraphQL

              An open-source query language and specification for APIs that enables clients to request specific data, promoting efficiency and flexibility in data retrieval.

              GraphQL server

              A server that contains a GraphQL schema and can resolve client-requested operations that are executed against that schema.

              mutations

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              arguments

              A key-value pair associated with a particular schema field that lets operations pass data to that field's resolver.

              Argument values can be hardcoded as literal values (shown below for clarity) or provided via GraphQL variables (recommended).

              query GetHuman {
              human(id: "200") {
              name
              height(unit: "meters")
              }
              }
              variables

              A placeholder for dynamic values in an operation allowing parameterization and reusability in requests. Variables can be used to fill arguments or passed to directives.

              query GetUser($userId: ID!) {
              user(id: $userId) {
              firstName
              }
              }

              In the query above, userId is a variable. The variable and its type are declared in the operation signature, signified by a $. The type of variable is a non-nullable ID. A variable's type must match the type of any argument it's used for.

              GraphQL

              An open-source query language and specification for APIs that enables clients to request specific data, promoting efficiency and flexibility in data retrieval.

              NEW COURSE ALERT

              Introducing Apollo Connectors

              Connectors are the new and easy way to get started with GraphQL, using existing REST APIs.

              Say goodbye to GraphQL servers and resolvers—now, everything happens in the schema!

              Take the course