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.

Access historical weather data through Archive Data retrieval requests. Historical data is available dating back to January 1, 1990.

Overview

Archive data retrieval is an asynchronous process:

  1. Submit an archive request

  2. Check job status (job progresses through several stages)

  3. Download files when ready

How It Works

Historical weather is Spire’s global reanalysis: hourly data at 1/8° from 1 January 1990 onwards, produced about six days behind real time. Requests that include the most recent six days are completed from Spire’s short-range historical forecasts (the 6-hourly analyses plus the first hours of each run); the output then contains one sub-folder per source, and issuance_time and valid_time can differ by up to five hours for those records.

Retrieval is asynchronous:

  1. Submit the route. The API validates it, reserves the waypoints against your account’s waypoint quota and returns a job_uuid. Keep it: you need it to check status and download the result.

  2. Poll the job status. It moves through the stages listed below. Every status response carries export_uri, the export location; once the status is completed the files are there, and the reserved waypoints are deducted from your quota. Waypoints of a failed job are returned to the quota. A one-waypoint test job completed in about two minutes.

  3. Download the output. List the export location: it returns one ZIP path of the form {export_id}/{export_id}.zip. Append that path to the export endpoint to download. The ZIP contains one folder per data source with a {route name}.json or .csv file inside.

Rules for the route:

Endpoints

MethodEndpointDescription
POST/archive/routeRequest archive data along a route
GET/archive/jobs/{job_uuid}/statusCheck archive job status
GET/export/{request_id}List files from archive request
GET/export/{request_id}/{file_id}Download archive file

Archive Route Request

POST /archive/route

Request historical weather data along a route with timestamps.

Request Body

The request body uses the same route structure as the forecast route endpoint, with additional options for variable selection and output format.

{
  "route": {
    "name": "historical_voyage",
    "waypoints": [
      {
        "lat": 40.0,
        "lon": -74.0,
        "time": "2023-06-15T12:00:00Z"
      },
      {
        "lat": 41.0,
        "lon": -70.0,
        "time": "2023-06-15T18:00:00Z"
      },
      {
        "lat": 42.0,
        "lon": -66.0,
        "time": "2023-06-16T00:00:00Z"
      }
    ]
  },
  "fields": [
    "air_temperature",
    "wind_speed",
    "wind_direction",
    "sea_surface_wave_significant_height"
  ],
  "output_format": "CSV"
}

Request Body Fields

FieldTypeRequiredDescription
routeobjectYesRoute definition
route.namestringNoName used for the output file (default route_1); letters, digits, underscores and hyphens only
route.waypointsarrayYesArray of waypoints (max 10,000)
route.waypoints[].latnumberYesLatitude
route.waypoints[].lonnumberYesLongitude
route.waypoints[].timestringYesISO 8601 timestamp
fieldsarrayOne of fields or bundlesVariable names to include
bundlesarrayOne of fields or bundlesArchive bundle names: core, agricultural, maritime, maritime-wave, maritime-swell-wave, sea-surface, precipitation, wind-energy, solar-energy, thunderstorm
output_formatstringNoJSON (default) or CSV

Example Request

Shell
Python
Node.js
curl -X POST \
  'https://api.wx.spire.com/archive/route' \
  -H 'spire-api-key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "route": {
      "name": "historical_voyage",
      "waypoints": [
        {"lat": 40.0, "lon": -74.0, "time": "2023-06-15T12:00:00Z"},
        {"lat": 42.0, "lon": -66.0, "time": "2023-06-16T00:00:00Z"}
      ]
    },
    "fields": ["air_temperature", "wind_speed", "sea_surface_wave_significant_height"],
    "output_format": "CSV"
  }'

Response

{
  "job_uuid": "3f2b9c1e-7a4d-4e0b-9c1a-2d6f8e5b7a10",
  "job_type": "RouteRetrievalJob",
  "job_status": "initiated",
  "creation_time": "2026-09-21T14:44:45+00:00",
  "export_uri": "https://api.wx.spire.com/export/3f2b9c1e-7a4d-4e0b-9c1a-2d6f8e5b7a10"
}

Keep the job_uuid; the status and export endpoints take it as their path parameter. export_uri is the export location you will list once the job is completed.


Check Job Status

GET /archive/jobs/{job_uuid}/status

Check the status of an archive data retrieval job.

Path Parameters

ParameterTypeRequiredDescription
job_uuidstringYesJob identifier from request

Example Request

Shell
Python
Node.js
curl -X GET \
  'https://api.wx.spire.com/archive/jobs/abc123-def456-789xyz/status' \
  -H 'spire-api-key: YOUR_API_KEY'

Response

{
  "job_uuid": "3f2b9c1e-7a4d-4e0b-9c1a-2d6f8e5b7a10",
  "job_type": "RouteRetrievalJob",
  "job_status": "completed",
  "creation_time": "2026-09-21T14:44:45+00:00",
  "export_uri": "https://api.wx.spire.com/export/3f2b9c1e-7a4d-4e0b-9c1a-2d6f8e5b7a10"
}

Status Values

Archive jobs progress through the stages below. The API returns the status in lower case.

StatusDescription
createdJob submitted
queuedWaiting for a processing slot
restoring_filesRetrieving archived data from storage
restore_completedArchived data retrieved, ready for extraction
initiatedExtraction process initiated
processingData extraction in progress
completedData ready for download
failedJob failed
timeoutJob exceeded its processing time limit
unknownStatus could not be determined

List Export Files

GET /export/{request_id}

Retrieve a list of files available from a completed archive request. The request_id is the job_uuid (the last path segment of export_uri). Route jobs return one entry of the form {export_id}/{export_id}.zip. An unknown or not yet completed request_id returns an empty files list, so check meta.count before downloading.

Path Parameters

ParameterTypeRequiredDescription
request_idstringYesRequest identifier from completed job

Example Request

Shell
Python
Node.js
curl -X GET \
  'https://api.wx.spire.com/export/3f2b9c1e-7a4d-4e0b-9c1a-2d6f8e5b7a10' \
  -H 'spire-api-key: YOUR_API_KEY'

Response

{
  "meta": {
    "count": 1
  },
  "files": [
    "8c1d2e3f-4a5b-4c6d-8e9f-0a1b2c3d4e5f/8c1d2e3f-4a5b-4c6d-8e9f-0a1b2c3d4e5f.zip"
  ]
}

The ZIP holds one folder per data source (the reanalysis, and the recent-forecast fill for the last six days when the route reaches into them) containing {route name}.json or .csv. A JSON record looks like this:

{
  "data": [
    {
      "coordinates": {"lat": 52.0, "lon": 4.0},
      "times": {
        "valid_time": "2026-09-01T12:00:00",
        "requested_valid_time": "2026-09-01T12:00:00"
      },
      "values": {"air_temperature": 291.5}
    }
  ]
}

Download Export File

GET /export/{request_id}/{file_id}

Download a specific file from an archive export.

Path Parameters

ParameterTypeRequiredDescription
request_idstringYesRequest identifier
file_idstringYesFilename to download

Example Request

Shell
Python
Node.js
curl -OJL -X GET \
  'https://api.wx.spire.com/export/3f2b9c1e-7a4d-4e0b-9c1a-2d6f8e5b7a10/8c1d2e3f-4a5b-4c6d-8e9f-0a1b2c3d4e5f/8c1d2e3f-4a5b-4c6d-8e9f-0a1b2c3d4e5f.zip' \
  -H 'spire-api-key: YOUR_API_KEY'

Python Example

Complete workflow for archive data retrieval:

import requests
import time

headers = {'spire-api-key': 'YOUR_API_KEY'}
base_url = 'https://api.wx.spire.com'

# 1. Submit archive request
route_data = {
    "route": {
        "name": "historical_voyage",
        "waypoints": [
            {"lat": 40.0, "lon": -74.0, "time": "2023-06-15T12:00:00Z"},
            {"lat": 41.0, "lon": -70.0, "time": "2023-06-15T18:00:00Z"},
            {"lat": 42.0, "lon": -66.0, "time": "2023-06-16T00:00:00Z"}
        ]
    },
    "fields": [
        "air_temperature",
        "wind_speed",
        "wind_direction",
        "sea_surface_wave_significant_height"
    ],
    "output_format": "CSV"
}

response = requests.post(
    f'{base_url}/archive/route',
    headers=headers,
    json=route_data
)
job = response.json()
job_uuid = job['job_uuid']
print(f"Job submitted: {job_uuid}")

# 2. Poll for completion
terminal_statuses = {'completed', 'failed', 'unknown'}
while True:
    status_response = requests.get(
        f'{base_url}/archive/jobs/{job_uuid}/status',
        headers=headers
    )
    status = status_response.json()
    print(f"Status: {status['job_status']}")

    if status['job_status'].lower() in terminal_statuses:
        break

    time.sleep(30)  # Wait before checking again

if status['job_status'].lower() != 'completed':
    raise Exception(f"Archive job ended with status: {status['job_status']}")

export_uri = status['export_uri']

# 3. List and download files
files_response = requests.get(
    export_uri,
    headers=headers
)
files = files_response.json()['files']

for filename in files:
    file_response = requests.get(
        f'{export_uri}/{filename}',
        headers=headers,
        allow_redirects=True
    )
    with open(filename.split('/')[-1], 'wb') as f:
        f.write(file_response.content)
    print(f'Downloaded: {filename}')