Back to Blog
Lesson 38 of the GraphQL: Your First GraphQL Schema & Server course
API ArchitectureAugust 25, 20264 min read

Fetching from a REST API: Integrating External Data into GraphQL

Learn to move beyond static data by fetching from a REST API in your GraphQL resolvers. Master data transformation and async integration for your server.

GraphQLRESTAPIJavaScriptBackendNode.js
Vibrant JavaScript code displayed on a screen, highlighting programming concepts and software development.

Previously in this course, we explored Asynchronous Resolvers. Now that you understand how to manage promises, we’ll move beyond static JSON files and connect your GraphQL server to a live, external REST API.

By the end of this lesson, you will be able to use fetch (or axios) inside your resolvers to pull data from a remote service and transform that raw REST structure to match your GraphQL schema perfectly.

Why Integrate REST into GraphQL?

Most modern applications don't live in a vacuum. Your GraphQL server acts as an orchestration layer—a "gateway"—that fetches data from various sources (databases, microservices, or third-party APIs) and presents a clean, unified interface to the client.

While we previously connected to JSON data stored locally, real-world services require dynamic, live data. REST integration allows your GraphQL API to act as a powerful wrapper, hiding the complexity of multiple endpoints from your frontend.

The Integration Pattern

The workflow is straightforward:

  1. Trigger: A GraphQL query hits a resolver.
  2. Fetch: The resolver makes an asynchronous GET request to a REST endpoint.
  3. Transform: The resolver maps the REST-style JSON response to your GraphQL schema's field names.
  4. Return: The GraphQL server sends the sanitized data to the client.

Worked Example: Fetching a User Profile

A dark, minimalist photo of a computer monitor displaying the ChatGPT interface.

Let's assume we want to fetch user data from a public placeholder API (https://jsonplaceholder.typicode.com).

1. Define the Schema

First, ensure your SDL matches the data you expect to receive:

GraphQL
type User {
  id: ID!
  name: String
  email: String
}

type Query {
  user(id: ID!): User
}

2. Implement the Resolver

We will use the native Node.js fetch API. In your resolver, you must await the response, parse the JSON, and map it.

JAVASCRIPT
const resolvers = {
  Query: {
    user: async (_, { id }) => {
      const response = await fetch(CE9178">`https://jsonplaceholder.typicode.com/users/${id}`);
      
      if (!response.ok) {
        throw new Error("Failed to fetch user from external API");
      }

      const data = await response.json();

      // Transform: Mapping REST keys to our GraphQL schema
      return {
        id: data.id,
        name: data.name,
        email: data.email
      };
    },
  },
};

Key Considerations for REST Integration

  • Error Handling: Unlike local files, network calls fail. Always check response.ok or wrap your fetch in a try/catch block to return meaningful errors to the client.
  • Transformation: REST APIs often return deeply nested objects or different naming conventions (like user_name vs name). The resolver is the perfect place to flatten or rename these fields to maintain your GraphQL schema's contract.
  • Performance: Every call to fetch adds network latency. If you resolve a list of users, you’ll trigger the N+1 problem. We will address this in the next lesson regarding the Data Loader pattern.

Hands-on Exercise

  1. Install node-fetch if you are using a Node version older than 18, or simply use the built-in fetch if you are on a modern version.
  2. Modify your current project's Query resolver to fetch a list of "posts" from https://jsonplaceholder.typicode.com/posts.
  3. Create a Post type in your schema with id, title, and body fields.
  4. Ensure your resolver returns an array that matches this schema structure.

Common Pitfalls

  • Ignoring Async: Forgetting to await the fetch call is the most common bug. If you return a promise instead of the resolved data, your API will return null or an unexpected object.
  • Over-fetching: Just because the REST API returns 20 fields doesn't mean your GraphQL resolver should pass them all through. Map only what your schema defines to keep the data layer clean.
  • Hardcoding URLs: Avoid hardcoding API URLs directly inside resolvers for large projects. Use environment variables or a dedicated service class to manage configuration.

FAQ

Q: Should I use fetch or axios? A: Both work perfectly. fetch is built into modern Node.js, making it great for simple projects. axios provides better features for interceptors and automatic JSON parsing, which are helpful in complex production environments.

Q: Does this make my GraphQL server slow? A: It adds network overhead. The goal is to consolidate multiple REST calls into one GraphQL response, which actually improves performance for the frontend by reducing the number of round-trips.

Q: Can I use fetch inside a field resolver (not just a root query)? A: Absolutely! This is the primary way to build "nested" relationships where a User has a field posts that fetches data from a different REST endpoint.

Recap

We’ve successfully moved from static data to dynamic REST integration. By using fetch inside our resolvers and transforming the resulting JSON, we’ve made our GraphQL API a true gateway for external data. Remember to always handle your network errors gracefully and keep your schema strictly typed.

Up next: The Data Loader Pattern — how to solve the N+1 problem when fetching lists of data from REST APIs.

Similar Posts