Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

API Basics


Overview

This notebook will cover the terminology and steps needed to retrieve data from an API

  1. Prerequisites

  2. Motivation

  3. API Terminology (and Status Codes)

  4. Imports

  5. Example: Weather API

  6. Summary

Prerequisites

ConceptsImportanceNotes
Intro to PandasNecessaryFamiliarity with working with dataframes
Intro to MatplotlibHelpfulPlotting on a data

Motivation

There are many ways to gather data. Science and research entities like NASA are constantly producing and collecting data. As a result, attempting to collect and display live data can be difficult since new data is always being added. An API is a method to query a data source for the most current data or retrieve data from a remote source. This notebook will cover the basics regarding API usage to improve ease of access to publicly available data.


API Terminology

  • API: Application Programming Interface which dictacts how code can communicate and access or update remote data through methods

  • Request: Code sends requests to an API to either retrieve or update data

  • GET: A GET request retrieves data

  • SET: A SET request updates data

When working with public APIs, most methods will request data from an API (a GET request)

Understanding Status Codes

There are multiple possible status codes that a request will return. For the purpose of simplicity, the two most important codes are:

  • 200 OK: The server was able to successfully process the request and return the requested data

  • 400 Bad Request: The server was not able to process the request do to an invalid request (usally the result of an invalid URL or unknown parameters)


Imports

Requests

The Requests Python package is a library that manages the requests made in Python

A request returns machine-readable data in a JSON. Among the data, requests returns:

  • request.status_code: status code of the request (200, 400, etc...)

  • request.text: data requested as a JSON

  • request.json(): fully JSON returned by the request


Example: Weather API

The National Weather Serivce manages an API for weather in the United States. The API is hosted at https://api.weather.gov/

The first step when working with an API should be to check that the API is fuctioning by querying a general request without any additional parameters.

200

Info

A 200 status code represents that the base API is working as expected and a query request returns no errors.

However, without any additional parameters, all the data that the request returns is just the status code.

The next step is to query with specific paramters. For the weather API the accepts either a grid around a NWS Weather Forecast Office or a specific latitude/longtiude position

The request will be formatted as:

https://api.weather.gov/points/<latitude>,<longitude>

More information about the documentation can be found at NWS Weather API.

For example, the location of the NCAR Mesa Lab is 39.97777 degrees latitude and -105.274966 degrees longitude

200

Success

With a valid request and paramters, this request will return data as well!

{'@context': ['https://geojson.org/geojson-ld/geojson-context.jsonld', {'@version': '1.1', 'wx': 'https://api.weather.gov/ontology#', 's': 'https://schema.org/', 'geo': 'http://www.opengis.net/ont/geosparql#', 'unit': 'http://codes.wmo.int/common/unit/', '@vocab': 'https://api.weather.gov/ontology#', 'geometry': {'@id': 's:GeoCoordinates', '@type': 'geo:wktLiteral'}, 'city': 's:addressLocality', 'state': 's:addressRegion', 'distance': {'@id': 's:Distance', '@type': 's:QuantitativeValue'}, 'bearing': {'@type': 's:QuantitativeValue'}, 'value': {'@id': 's:value'}, 'unitCode': {'@id': 's:unitCode', '@type': '@id'}, 'forecastOffice': {'@type': '@id'}, 'forecastGridData': {'@type': '@id'}, 'publicZone': {'@type': '@id'}, 'county': {'@type': '@id'}}], 'id': 'https://api.weather.gov/points/39.9778,-105.275', 'type': 'Feature', 'geometry': {'type': 'Point', 'coordinates': [-105.275, 39.9778]}, 'properties': {'@id': 'https://api.weather.gov/points/39.9778,-105.275', '@type': 'wx:Point', 'cwa': 'BOU', 'type': 'land', 'forecastOffice': 'https://api.weather.gov/offices/BOU', 'gridId': 'BOU', 'gridX': 54, 'gridY': 73, 'forecast': 'https://api.weather.gov/gridpoints/BOU/54,73/forecast', 'forecastHourly': 'https://api.weather.gov/gridpoints/BOU/54,73/forecast/hourly', 'forecastGridData': 'https://api.weather.gov/gridpoints/BOU/54,73', 'observationStations': 'https://api.weather.gov/gridpoints/BOU/54,73/stations', 'relativeLocation': {'type': 'Feature', 'geometry': {'type': 'Point', 'coordinates': [-105.251251, 40.0244306]}, 'properties': {'city': 'Boulder', 'state': 'CO', 'distance': {'unitCode': 'wmoUnit:m', 'value': 0}, 'bearing': {'unitCode': 'wmoUnit:degree_(angle)', 'value': 0}}}, 'forecastZone': 'https://api.weather.gov/zones/forecast/COZ035', 'county': 'https://api.weather.gov/zones/county/COC013', 'fireWeatherZone': 'https://api.weather.gov/zones/fire/COZ215', 'timeZone': 'America/Denver', 'radarStation': 'KFTG', 'astronomicalData': {'sunrise': '2026-10-31T07:29:21-06:00', 'sunset': '2026-10-31T18:00:02-06:00', 'transit': '2026-10-31T12:44:42-06:00', 'civilTwilightBegin': '2026-10-31T07:01:24-06:00', 'civilTwilightEnd': '2026-10-31T18:27:59-06:00', 'nauticalTwilightBegin': '2026-10-31T06:29:28-06:00', 'nauticalTwilightEnd': '2026-10-31T18:59:55-06:00', 'astronomicalTwilightBegin': '2026-10-31T05:57:57-06:00', 'astronomicalTwilightEnd': '2026-10-31T19:31:26-06:00'}, 'nwr': {'transmitter': 'WXM51', 'sameCode': '008013', 'areaBroadcast': 'https://api.weather.gov/radio/WXM51/broadcast', 'pointBroadcast': 'https://api.weather.gov/points/39.9778,-105.275/radio'}}}

With the latitude and longtiude of a position, the API will return information about the closest NWS forecast office that can be further queried to return the weather. A JSON acts like a Python dictionary; to return the values stored, json() can be queried for a specific key.

<class 'dict'>

key: @context
value: ['https://geojson.org/geojson-ld/geojson-context.jsonld', {'@version': '1.1', 'wx': 'https://api.weather.gov/ontology#', 's': 'https://schema.org/', 'geo': 'http://www.opengis.net/ont/geosparql#', 'unit': 'http://codes.wmo.int/common/unit/', '@vocab': 'https://api.weather.gov/ontology#', 'geometry': {'@id': 's:GeoCoordinates', '@type': 'geo:wktLiteral'}, 'city': 's:addressLocality', 'state': 's:addressRegion', 'distance': {'@id': 's:Distance', '@type': 's:QuantitativeValue'}, 'bearing': {'@type': 's:QuantitativeValue'}, 'value': {'@id': 's:value'}, 'unitCode': {'@id': 's:unitCode', '@type': '@id'}, 'forecastOffice': {'@type': '@id'}, 'forecastGridData': {'@type': '@id'}, 'publicZone': {'@type': '@id'}, 'county': {'@type': '@id'}}]

key: id
value: https://api.weather.gov/points/39.9778,-105.275

key: type
value: Feature

key: geometry
value: {'type': 'Point', 'coordinates': [-105.275, 39.9778]}

key: properties
value: {'@id': 'https://api.weather.gov/points/39.9778,-105.275', '@type': 'wx:Point', 'cwa': 'BOU', 'type': 'land', 'forecastOffice': 'https://api.weather.gov/offices/BOU', 'gridId': 'BOU', 'gridX': 54, 'gridY': 73, 'forecast': 'https://api.weather.gov/gridpoints/BOU/54,73/forecast', 'forecastHourly': 'https://api.weather.gov/gridpoints/BOU/54,73/forecast/hourly', 'forecastGridData': 'https://api.weather.gov/gridpoints/BOU/54,73', 'observationStations': 'https://api.weather.gov/gridpoints/BOU/54,73/stations', 'relativeLocation': {'type': 'Feature', 'geometry': {'type': 'Point', 'coordinates': [-105.251251, 40.0244306]}, 'properties': {'city': 'Boulder', 'state': 'CO', 'distance': {'unitCode': 'wmoUnit:m', 'value': 0}, 'bearing': {'unitCode': 'wmoUnit:degree_(angle)', 'value': 0}}}, 'forecastZone': 'https://api.weather.gov/zones/forecast/COZ035', 'county': 'https://api.weather.gov/zones/county/COC013', 'fireWeatherZone': 'https://api.weather.gov/zones/fire/COZ215', 'timeZone': 'America/Denver', 'radarStation': 'KFTG', 'astronomicalData': {'sunrise': '2026-10-31T07:29:21-06:00', 'sunset': '2026-10-31T18:00:02-06:00', 'transit': '2026-10-31T12:44:42-06:00', 'civilTwilightBegin': '2026-10-31T07:01:24-06:00', 'civilTwilightEnd': '2026-10-31T18:27:59-06:00', 'nauticalTwilightBegin': '2026-10-31T06:29:28-06:00', 'nauticalTwilightEnd': '2026-10-31T18:59:55-06:00', 'astronomicalTwilightBegin': '2026-10-31T05:57:57-06:00', 'astronomicalTwilightEnd': '2026-10-31T19:31:26-06:00'}, 'nwr': {'transmitter': 'WXM51', 'sameCode': '008013', 'areaBroadcast': 'https://api.weather.gov/radio/WXM51/broadcast', 'pointBroadcast': 'https://api.weather.gov/points/39.9778,-105.275/radio'}}

The closest forecast office from the NCAR Mesa Lab is forecastOffice

'https://api.weather.gov/offices/BOU'

The query also return the hourly forecast as a further URL to query as a request under forecastHourly

'https://api.weather.gov/gridpoints/BOU/54,73/forecast/hourly'
200

Note

There is a lot more data returned from this request! The forecast information can be collected under properties and period. Each period of time has various weather values to chose from:

dict_keys(['number', 'name', 'startTime', 'endTime', 'isDaytime', 'temperature', 'temperatureUnit', 'temperatureTrend', 'probabilityOfPrecipitation', 'dewpoint', 'relativeHumidity', 'windSpeed', 'windDirection', 'icon', 'shortForecast', 'detailedForecast'])

To plot, let’s collect the startTime, endTime and temperature (° F) values

2026-10-30T21:00:00-06:00
2026-11-06T08:00:00-07:00
[51, 50, 50, 49, 48, 48, 46, 46, 46, 46, 45, 47, 48, 51, 53, 56, 58, 60, 62, 60, 60, 55, 51, 51, 50, 49, 51, 48, 47, 47, 46, 46, 47, 46, 47, 47, 48, 50, 52, 54, 57, 59, 60, 59, 57, 54, 53, 52, 52, 52, 52, 52, 51, 51, 50, 50, 50, 50, 49, 49, 48, 48, 49, 50, 51, 52, 52, 50, 48, 46, 46, 45, 45, 45, 44, 44, 43, 42, 41, 41, 41, 42, 42, 42, 43, 46, 49, 52, 55, 57, 58, 56, 53, 50, 48, 46, 45, 44, 44, 43, 42, 41, 41, 41, 42, 42, 42, 42, 43, 46, 50, 53, 55, 56, 56, 54, 51, 48, 46, 45, 44, 43, 43, 42, 41, 40, 39, 39, 39, 40, 40, 41, 42, 44, 47, 49, 51, 53, 53, 51, 49, 46, 44, 43, 42, 41, 41, 41, 41, 40, 40, 40, 40, 41, 41, 42]
<Figure size 2200x1000 with 1 Axes>

Success

We have ploted the forecasted hourly temperatures for the next week!


Summary

In this notebook, we have...

  • covered basics about API terminology

  • gone through a practice example of requesting data from the National Weather Service API

  • generated a plot of forecasted temperatures

What’s next?

Now we can continue investigating other APIs using some example workflows in this cookbook.