Skip to main content

Module 6 β€” External API Requests

Fetch real data from the internet and render it in your pages.

Overview πŸ“‹

APIs (Application Programming Interfaces) allow applications to communicate with each other over the internet. In web development, this almost always means sending HTTP requests to a server and getting back JSON data. JavaScript's fetch API, combined with async/await, makes this straightforward. This module covers how to make GET and POST requests, handle responses, and deal with errors.

Why This Matters πŸ’‘

Almost every real application pulls data from an external source β€” weather data, user profiles, product listings, financial data. Knowing how to make API calls and handle the responses is one of the most practical skills in front-end development. It is also your first direct encounter with asynchronous programming, which is fundamental to JavaScript.

Learning Goals 🎯

By the end of this module you should be able to:

  • Understand what an API is and how HTTP requests work
  • Use fetch with async/await to make GET requests
  • Parse JSON responses
  • Handle errors with try/catch
  • Make a POST request with a JSON body
  • Use Postman to test an API before writing code
  • Display fetched data in the DOM

Vocabulary πŸ“–

TermDefinition
APIA set of rules for how two applications communicate
HTTPThe protocol used to send requests and responses over the web
GETAn HTTP method for reading data
POSTAn HTTP method for sending data to create or update a resource
JSONJavaScript Object Notation β€” a data format for APIs
PromiseAn object representing a future value from an async operation
async/awaitSyntax for writing asynchronous code that looks synchronous
Status codeA number indicating the result of a request (200 = OK, 404 = not found, 500 = server error)

Core Concepts 🧠

Making a GET request

// async function with error handling
const fetchUser = async (id) => {
  try {
    const response = await fetch(`https://api.example.com/users/${id}`)

    if (!response.ok) {
      throw new Error(`request failed: ${response.status}`)
    }

    const data = await response.json()
    return data
  } catch (error) {
    console.error('fetch error:', error)
  }
}

Making a POST request

const createUser = async (userData) => {
  try {
    const response = await fetch('https://api.example.com/users', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(userData),
    })

    if (!response.ok) {
      throw new Error(`request failed: ${response.status}`)
    }

    const newUser = await response.json()
    return newUser
  } catch (error) {
    console.error('create user error:', error)
  }
}

Rendering fetched data to the DOM

const loadPokemon = async (name) => {
  const response = await fetch(`https://pokeapi.co/api/v2/pokemon/${name}`)
  const pokemon = await response.json()

  const img = document.querySelector('#pokemon-img')
  const title = document.querySelector('#pokemon-name')

  img.src = pokemon.sprites.front_default
  title.textContent = pokemon.name
}

loadPokemon('pikachu')

Examples πŸ’»

Fetching and rendering a list from a public API:

const renderPosts = async () => {
  const response = await fetch('https://jsonplaceholder.typicode.com/posts?_limit=5')
  const posts = await response.json()

  const list = document.querySelector('#posts')

  posts.forEach((post) => {
    const item = document.createElement('li')
    item.textContent = post.title
    list.appendChild(item)
  })
}

renderPosts()

Handling a loading state:

const loadData = async () => {
  const status = document.querySelector('#status')
  status.textContent = 'loading...'

  try {
    const response = await fetch('https://api.example.com/data')
    const data = await response.json()
    status.textContent = ''
    renderData(data)
  } catch (error) {
    status.textContent = 'something went wrong. try again.'
  }
}

Common Mistakes ⚠️

  • Not checking response.ok. A 404 or 500 response does not throw an error β€” fetch only rejects on network failures. Always check response.ok before calling .json().
  • Forgetting await. Without await, you get a Promise object instead of the data. This is one of the most common bugs in async code.
  • Not wrapping in try/catch. If the network is down or the server returns an error, your app crashes silently. Always handle the error case.
  • Calling an async function and using the return value directly. Async functions return Promises. You need to await them or use .then().
  • Forgetting Content-Type header on POST. Without it, the server may not know how to parse your request body.

Debugging Tips πŸ”

  • Use Postman to test an API endpoint before writing any JavaScript. Confirm you get the expected data shape.
  • Open DevTools β†’ Network tab to inspect real requests: URL, method, status code, request headers, and response body.
  • console.log(response.status) before calling .json() to see if the request succeeded.
  • If you get a CORS error, the API does not allow requests from your origin. Look for a public CORS-friendly version, use a proxy, or call it from your own backend.
  • Check the response structure with console.log(data) before trying to access nested properties.

Exercise πŸ‹οΈ

The exercise for this module is in the class repository:

ttpr-lagcc-spring-2026 β†’ Module 6 Exercise (opens in new tab)

Build a PokΓ©mon lookup app using the PokΓ©API (opens in new tab). A user types a PokΓ©mon name, clicks a button, and the app fetches and displays the PokΓ©mon's image, name, and types. Handle loading and error states.

Additional Resources πŸ“š

Recap Checklist βœ”οΈ

  • I understand what an HTTP request and response are
  • I can use fetch with async/await to make a GET request
  • I check response.ok before processing the response
  • I handle errors using try/catch
  • I can make a POST request with a JSON body and correct headers
  • I can render fetched data to the DOM
  • I know how to use the Network tab in DevTools to inspect requests