Working with APIs & Structured Data

A 2-hour practical workshop for researchers using JavaScript to work with data, starting from lesson_2.zip

Overview

This workshop introduces Application Programming Interfaces (APIs) and structured data formats commonly used in research and public data portals.

Participants will learn how to request data from an API, interpret structured responses, and display results in a clean, readable format using JavaScript.

  • Duration: 2 hours
  • Outcome: A webpage that automatically loads and displays weather forecast data

What Are APIs?

An API is a structured way for software systems to share data. For researchers, APIs provide programmatic access to datasets that are frequently updated or too large to download manually.

Common research uses of APIs include:

  • Accessing public datasets (environmental data, census, etc.)
  • Automating data collection (e.g., fetching weather data every hour)
  • Ensuring reproducibility
  • Building interactive research outputs

Common Structured Data Formats

JSON

JavaScript Object Notation. Human-readable, widely used, and native to JavaScript.

GeoJSON

A geographic extension of JSON for spatial data (points, lines, polygons).

CSV

Comma-Separated Values. Common for spreadsheets and tabular research data.

XML

Extensible Markup Language. Older but still used in many scholarly systems.

In this workshop, we focus on JSON and GeoJSON because they work naturally with JavaScript.

The National Weather Service (NWS) API

The NWS provides a free, public API that returns weather forecasts in JSON format.

A typical request looks like this:

https://api.weather.gov/points/39.7456,-97.0892

This endpoint returns metadata, including a link to the forecast for that location. See the NWS API Web Service page for details.

Mini Exercise (5–7 min)

Explore the NWS API response in your browser.

Using the Visitor’s Location

Instead of hard-coding latitude and longitude, we can use the browser’s navigator.geolocation API.

navigator.geolocation.getCurrentPosition(position => {
  const lat = position.coords.latitude;
  const lon = position.coords.longitude;
});

These coordinates can then be used to replace 39.7456,-97.0892 dynamically.

Fetching Data with JavaScript

JavaScript uses the fetch() function to request data from an API.


async function get_weather_forcast(lat, lon) {
  console.log("Fetching forecast for:", lat, lon);
  const pointsRes = await fetch(`https://api.weather.gov/points/${lat},${lon}`);
  const pointsData = await pointsRes.json();

  const forecastRes = await fetch(pointsData.properties.forecast);
  return await forecastRes.json();
}
        

fetch() returns a Promise, not the data, and is often used with the following to complete the request:

  1. async allows operations to run without blocking the main program thread, ensuring the application remains responsive
  2. await used to pause the execution of an async function until a Promise is settled (fulfilled or rejected)

This chained request pattern is common when working with linked APIs.

Then What

.then() is a method used with Promises to handle the results of asynchronous operations. The updated geolocation below shows how to work with .then()



navigator.geolocation.getCurrentPosition(position => {
  let lat = position.coords.latitude;
  let lon = position.coords.longitude;

  get_weather_forcast(lat,lon)
    .then(data => {
    update_forcast(data);
    }              
  )
});
        

Looping Over Forecast Data

The forecast response includes an array of time periods. We can loop over this data and build a table.

forecastData.properties.periods.forEach(period => {
  console.log(period.name, period.temperature, period.shortForecast);
});

Displaying Data in a Table

<table id="forecast">
  <thead>
    <tr>
      <th>Period</th>
      <th>Temperature</th>
      <th>Forecast</th>
    </tr>
  </thead>
  <tbody></tbody>
</table>

const tbody = document.querySelector('#forecast tbody');
tbody.innerHTML = ""; // Clear existing rows  
forecastData.properties.periods.forEach(period => {
  const row = document.createElement('tr');

  row.innerHTML = `
    <td>${period.name}</td>
    <td>${period.temperature}°F</td>
    <td>${period.shortForecast}</td>
  `;

  tbody.appendChild(row);
});

This approach cleanly separates data retrieval from presentation.

To make this table much more visually appealing, the following CSS can be used:


table {
  width: 100%;
  border-collapse: collapse;
  margin: 2rem 0;
  font-size: 0.95rem;
  background-color: #ffffff;
  border-radius: 0.5rem;
  overflow: hidden;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
}

thead {
  background-color: #0f172a;
  color: #ffffff;
}

thead th {
  text-align: left;
  padding: 0.75rem 1rem;
  font-weight: 600;
  letter-spacing: 0.02em;
}

tbody tr {
  border-bottom: 1px solid #e5e7eb;
}

tbody tr:nth-child(even) {
  background-color: #f8fafc;
}

tbody tr:hover {
  background-color: #eef2ff;
}

td {
  padding: 0.75rem 1rem;
  vertical-align: top;
}

       

Mini Exercise (5–7 min)

Update the HTML Table and JavaScriptforecastData forEach loop to include the icon property

  • Create new HTML
  • th
  • element
  • Update Javascript 'template' string
When you're done, save the file and test it in your web browser.

Web Services

Web services are powerful network-accessible resources capable of being pulled into your website. There are plenty of web services available for developers to use in their projects.

The ArcGIS Living Atlas of the World is a great index of these, with lots to choose from. We'll use the Current Weather and Wind Station Data.
ArcGIS Online, the plaform that powers the ArcGIS Living Atlas, uses a consistent API structure for all its web services.

Let's look at how to work with this API and pull in some weather station data. From the Current Weather and Wind Station Data page, you should see a link to the REST API on the right labled URL.

  1. Navigating to this page will bring you to the REST Services Directory.
  2. From here, clicking the Layers link for stations will bring you to the Layer page for the station data.
  3. On the bottom of this page is the link to query the data. Clicking the query link reveals the Query:Stations form.
    This complex form isn't as itimitating as it looks as we only have to fill out a few fields to get data back. Make the following entrys:
    • where: 1=1
    • outFields: *
    • And change the Formate to: GEOJSON
  4. Then click Query (GET)
We'll use this URL in the next lesson.
Note: if you only want to return one record, set "Result Record Count:" to 1. Great to testing large datasets!

The complete code for this example can been seen at lesson 3, and can be download from lesson_3.zip.