Using GraphQL

Introduction

GraphQL is a way of building and accessing APIs that allows for more flexibility and efficiency than traditional REST API endpoints. The REST API paradigm provides many endpoints but no customization within those endpoints, which can lead to over/underfetching data. GraphQL provides only one endpoint, but allows for complete customization over what data is received.

GraphQL gives you exactly what you ask for, and does it in a way that is intuitive and efficient.

Accessing Data

You can access our GraphQL endpoint using an HTTP Post Request, shown in the example requests below.

Copy
curl -X POST -H "Content-Type: application/json" \
 -H "Authorization: Bearer <YOUR API KEY HERE>" \
 --data '{ "query": "{ courseCatalog { nodes { title } } }" }' \
https://paas-api.pluralsight.com/graphql

You can also use the GraphQL Playground to quickly test all available queries and mutations (API Key needed).

For JavaScript/TypeScript usage, there are libraries built for GraphQL integrations. For example, the Graphios library simplifies back-end interactions with GraphQL servers. And the Apollo Client library makes it easy to build UI components that fetch data via GraphQL.

Pagination

The customizable nature of GraphQL makes it possible to fetch vast amounts of data in a single query. While this is a useful feature, there are instances in which it is not possible or desirable to receive all the data at once. Pagination allows you to fetch data in manageable batches.

Our GraphQL API implements cursor-based pagination. This type of pagination allows you to specify how many pieces of data you want to read, and where you want to start reading from. Each data entry has a cursor, which is an opaque string identifying the entry's place in the greater dataset.

Queries that offer pagination will have the following two parameters:

  • first: Specifies how many records to fetch.
  • after: Used to request the next result set from the query. Your query will return the value PageInfo.endCursor, and you should put that value here for the next query.

Let's walk through an example with the channels query, fetching 10 records at a time. We start with the following query, and get the corresponding result.

REQUEST
Copy
query {
  channels(first: 10) {
    totalCount
    pageInfo {
      endCursor
      hasNextPage
    }
    nodes {
      id
    }
  }
}
RESPONSE

{
  "data": {
    "channels": {
      "totalCount": 1710,
      "pageInfo": {
        "endCursor": "MTcxOTA3",
        "hasNextPage": true
      },
      "nodes": [
        {
          "id": "51427947-12d9-4bbf-aae8-5258c596cdd7"
        },
        ...9 more records
      ]
    }
  }
}

Notice the pageInfo.endCursor returned in the response, as this becomes the after of our next query.

REQUEST
Copy
query {
  channels(
    first: 10, 
    after: "MTcxOTA3") 
  {
    totalCount
    pageInfo {
      endCursor
      hasNextPage
    }
    nodes {
      id
    }
  }
}
RESPONSE

{
  "data": {
    "channels": {
      "totalCount": 1710,
      "pageInfo": {
        "endCursor": "MTcxMzIx",
        "hasNextPage": true
      },
      "nodes": [
        {
          "id": "9c641b7a-3931-4e2f-bbf4-0c57a7582c66"
        },
        ...9 more records
      ]
    }
  }
}

There are two final important pieces:

  • totalCount: indicates the total number of records that can be fetched. This helps you know how many batches you will need to fetch.
  • pageInfo.hasNextPage: boolean indicating whether there is more data to be fetched.

Filters

Many of our queries have an optional filter parameter that allows you to filter data based on fields such as name, availability, or date, as in the following two examples.

First, let's say you want to retrieve all free, published courses having to do with JavaScript. You could accomplish that with the following query:

Copy
query {
  courseCatalog(filter: {
    searchTerm: "javascript",
    free: true,
    status: "published"
  }) {
    nodes {
      title
    }
  }
}

Second, let's say you want to retrieve all skillIq assessments for your plan completed during the last month of 2019. You could accomplish that with the following query:

Copy
query {
  skillIqs(filter: {
    afterDate: "2019-11-30",
    beforeDate: "2020-01-01"
  }) {
    nodes {
      skillName,
      approximateLevel,
    }
  }
}

Additional Resources

About GraphQL

GraphQL: The Big Picture

Building Scalable APIs with GraphQL

Comparison of REST and GraphQL

The Fullstack Tutorial for GraphQL

Information about the Apollo Platform

Cursor-Based Pagination (See Complete Connection Model)