How to Connect to a GraphQL API

How to use an existing GraphQL API as a data source for your project

StepZen provides different custom directives for connecting to various kinds of data sources:

  • The @dbquery directive for connecting to databases.
  • The @rest directive for connecting to REST endpoints.
  • The @graphql directive for connecting to GraphQL APIs.

The following sections describe how to connect to a GraphQL API:

Connect to Public APIs

Follow the steps below to connect to public APIs:

  1. Ensure you have a StepZen account. In this example, see how to connect to the public Rick and Morty GraphQL API using the @graphql directive. Later you will see how to connect to an API that requires authorization.
  2. Perform the steps in the following subsections:

Create the Project Structure

Execute the following commands to create a project called rick-and-morty with a single directory called schema for the types:

mkdir -p rick-and-morty/schema
cd rick-and-morty

Create an index.graphql File

The index.graphql file tells StepZen how to assemble the various type definition files into a complete GraphQL schema.

touch index.graphql

This example only has a single file for now called characters.graphql:

schema @sdl(
  files: [
    "schema/characters.graphql"
  ]
) {
  query: Query
}

Create a characters.graphql File

Create a file called characters.graphql for the Character object:

touch schema/characters.graphql

The Character object has three fields:

FieldTypeDescription
idIDIdentifier
nameStringCharacter's name
imageStringURL to a .jpeg image file of the character
type Character {
  id: ID
  name: String
  image: String
}

To match the Rick and Morty API schema, return a results array containing the Character objects and call the type Characters:

type Characters {
  results: [Character]
}

The Query type has a characters query that returns the Characters, as specified in the previous types. The @graphql directive takes the endpoint of the GraphQL API, which in this case is https://rickandmortyapi.com/graphql, with the URL placed in between quotation marks:

type Query {
  characters: Characters
    @graphql(
      endpoint: "https://rickandmortyapi.com/graphql"
    )
}

Run CHARACTERS_QUERY Test Query

Run the following query called CHARACTERS_QUERY to test the new endpoint. This executes the characters query and returns an array of Character objects with their id, name, and image:

query CHARACTERS_QUERY {
  characters {
    results {
      id
      name
      image
    }
  }
}

This returns a data object containing the id, name, and image of the characters contained within a results array.

{
  "data": {
    "characters": {
      "results": [
        {
          "id": "1",
          "image": "https://rickandmortyapi.com/api/character/avatar/1.jpeg",
          "name": "Rick Sanchez"
        },
        {
          "id": "2",
          "image": "https://rickandmortyapi.com/api/character/avatar/2.jpeg",
          "name": "Morty Smith"
        }
      ]
    }
  }
}

Connect to Authenticated APIs

Now let's try a slightly more complex example. The Rick and Morty API is public, meaning that it does not require an API token to access. What if you wanted to use a headless CMS with the @graphql directive?

If you want to follow along with your own example, you can see how to authenticate with the Storyblok GraphQL API at the following link.

Create a config.yaml file

Much like the @rest directive, pass your query a configuration contained in a config.yaml file:

touch config.yaml

The config.yaml file contains a token provided by Storyblok that requires the following:

  • A name called storyblok_config.
  • A token provided by Storyblok. Substitute xxxx in the example below with the value:
configurationset:
  - configuration:
      name: storyblok_config
      token: xxxx

Create a storyblok.graphql file

The storyblok.graphql file has the content types and queries:

touch schema/storyblok.graphql

Define the following:

  • A PostItem type with a name of type String.
  • A PostItems type with an array named items containing PostItem objects.
type PostItem {
  name: String
}

type PostItems {
  items: [PostItem]
}

The Query type has a postItems query that returns the PostItems as specified in previous types. The @graphql directive takes:

  • The endpoint of the GraphQL API (https://gapi.storyblok.com/v1/api).
  • The configuration named storyblok_config.
  • The headers, which is an array of objects each containing the name and value of a header:
type Query {
  postItems: PostItems
    @graphql(
      endpoint: "https://gapi.storyblok.com/v1/api"
      headers: [
        { name:"Token" value:"$token" }
      ]
      configuration: "storyblok_config"
    )
}

Add schema/storyblok.graphql to your index.graphql file inside the files array:

schema @sdl(
  files: [
    "schema/characters.graphql"
    "schema/storyblok.graphql"
  ]
) {
  query: Query
}

Run POSTS_QUERY Test Query

Run the following query called POSTS_QUERY to test the new endpoint and execute the PostItems query:

query POSTS_QUERY {
  PostItems {
    items {
      name
    }
  }
}

This returns a data object containing the name of the PostItems contained within an items array:

{
  "data": {
    "PostItems": {
      "items": [
        {
          "name": "my-super-awesome-post"
        }
      ]
    }
  }
}

What else can I do with the @graphql Directive?

The @graphql directive provides a variety of extra functionality not explored in this simple example.

Mutations

So far you have only seen how to run queries. But you can also use the @graphql directive with Mutations as well.

You can find examples for how to use Mutations in the GraphQL Mutation Basics section.

Fragments

Let's say you have a relatively complicated page in your app that looks at two characters side by side, along with their friends. For more complicated queries, GraphQL includes reusable units called fragments.

Fragments let you construct sets of fields to include in your queries. This is useful for queries where you need to repeat the fields. The GraphQL docs include the following example:

{
  leftComparison: hero(episode: EMPIRE) {
    ...comparisonFields
  }
  rightComparison: hero(episode: JEDI) {
    ...comparisonFields
  }
}

fragment comparisonFields on Character {
  name
  appearsIn
  friends {
    name
  }
}

This results in the following output:

{
  "data": {
    "leftComparison": {
      "name": "Luke Skywalker",
      "appearsIn": [
        "NEWHOPE",
        "EMPIRE",
        "JEDI"
      ],
      "friends": [
        {
          "name": "Han Solo"
        },
        {
          "name": "Leia Organa"
        },
        {
          "name": "C-3PO"
        },
        {
          "name": "R2-D2"
        }
      ]
    },
    "rightComparison": {
      "name": "R2-D2",
      "appearsIn": [
        "NEWHOPE",
        "EMPIRE",
        "JEDI"
      ],
      "friends": [
        {
          "name": "Luke Skywalker"
        },
        {
          "name": "Han Solo"
        },
        {
          "name": "Leia Organa"
        }
      ]
    }
  }
}

Prefixes

As your project grows, you may connect to multiple APIs which result in name collisions for the types and queries. For example, if you have multiple characters queries, you may want the characters from the Rick and Morty API and not the Star Wars API.

In this example, append the prefix value rick_ to the types and queries. Instead of Character, write rick_Character, and so on:

type rick_Character {
  id: ID
  name: String
  image: String
}

type rick_Characters {
  results: [rick_Character]
}

Append a prefix by including an object containing a value with that prefix.

type Query {
  rick_characters: rick_Characters
    @graphql(
      endpoint: "https://rickandmortyapi.com/graphql"
      prefix: { value: "rick_", includeRootOperations: true }
    )
}

This site uses cookies: By using this website, you consent to our use of cookies in accordance with our Website Terms of Use and Cookie Policy.