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.

Reference for common data structures in API responses.

Point Forecast Response

The standard response format for point-based endpoints.

{
  "meta": {
    "unit_system": "si",
    "forecast": "Spire SOF-D Forecast",
    "units": {
      "air_temperature": "degreeK",
      "relative_humidity": "%",
      "wind_speed": "m/s",
      "wind_direction": "deg",
      "orography": "m"
    }
  },
  "data": [
    {
      "location": {
        "coordinates": {
          "lat": 40.0,
          "lon": -105.0,
          "elevation": 1655.0
        }
      },
      "times": {
        "issuance_time": "2024-01-15T00:00:00+00:00",
        "valid_time": "2024-01-15T06:00:00+00:00"
      },
      "values": {
        "air_temperature": 275.5,
        "relative_humidity": 65.0,
        "wind_speed": 5.2,
        "wind_direction": 225
      }
    }
  ]
}

Schema

FieldTypeDescription
metaobjectResponse metadata
meta.unit_systemstringUnit system used: si, us or us-f
meta.forecaststringProduct name, e.g. Spire SOF-D Forecast, Spire Optimized Point Forecast, Spire Current Weather Conditions
meta.unitsobjectUnit of every field that can appear in values
dataarrayArray of forecast records
data[].locationobjectLocation information
data[].location.coordinates.latnumberLatitude
data[].location.coordinates.lonnumberLongitude
data[].location.coordinates.elevationnumberModel terrain elevation at the grid point, metres above sea level
data[].timesobjectTemporal information
data[].times.issuance_timestringForecast model run time (Issuance Time)
data[].times.valid_timestringForecast Valid Time
data[].times.requested_valid_timestringRoute endpoint only: the waypoint time you asked for
data[].valuesobjectWeather values

The optimized point endpoint adds name, icao, wmo, unlocode and uuid to location.


File List Response

Response format for file listing endpoints.

{
  "meta": {
    "count": 49,
    "issuance_time": "2024-01-15T00:00:00+00:00"
  },
  "files": [
    "sof-d.20240115.t00z.0p125.basic.global.f000.grib2",
    "sof-d.20240115.t00z.0p125.basic.global.f001.grib2"
  ]
}

Schema

FieldTypeDescription
metaobjectResponse metadata
meta.countintegerNumber of files
meta.issuance_timestringForecast file listings only: the issuance the files belong to
meta.messagestringOptional human-readable note
filesarrayList of filenames

Route Schema

Format of the route object used by /forecast/route, /archive/route and /insights/maritime/route. The forecast route takes bundles as a query parameter; the archive route takes fields or bundles (an array) in the body, see Archive Data.

{
  "route": {
    "name": "my_route",
    "waypoints": [
      {
        "lat": 40.7,
        "lon": -74.0,
        "time": "2024-01-15T12:00:00Z"
      },
      {
        "lat": 38.5,
        "lon": -70.0,
        "time": "2024-01-16T00:00:00Z"
      }
    ]
  }
}

Schema

FieldTypeRequiredDescription
routeobjectYesRoute definition
route.namestringNoName for the route (used in archive output file names)
route.waypointsarrayYesArray of waypoints (max 120 for forecast and insights routes, 10,000 for archive routes)
route.waypoints[].latnumberYesLatitude
route.waypoints[].lonnumberYesLongitude
route.waypoints[].timestringYesISO 8601 timestamp

Storm Track Response

Response format for storm tracking endpoints. Wind speeds are in knots and pressures in hPa.

[
  {
    "atcf_id": "AL022024",
    "storm_name": "Beryl",
    "basin": "NA",
    "subbasin": "CS",
    "season": 2024,
    "is_active": false,
    "advisory_number": null,
    "advisory_issuance_time": null,
    "max_development_category": "TC5",
    "max_sustained_wind": 143.0,
    "min_mslp": 934.0,
    "dates_active": {
      "start": "2024-06-28",
      "end": "2024-07-09"
    },
    "observed_track": [
      {
        "lat": 10.5,
        "lon": -45.2,
        "category_code": "TD",
        "basin": "NA",
        "subbasin": "MM",
        "wind_gusts": null,
        "max_sustained_wind": 30.0,
        "min_mslp": 1006.0,
        "movement_direction": 280.0,
        "movement_speed": 18.0,
        "wind_extent_radii": {},
        "time": "2024-06-28T00:00:00+00:00"
      }
    ],
    "forecast_track": []
  }
]

Schema

FieldTypeDescription
atcf_idstringATCF ID storm identifier
storm_namestringStorm name (empty until named)
basinstringOcean basin code
subbasinstringSub-basin code
seasonintegerStorm season year
is_activebooleanWhether storm is currently active
max_development_categorystringMaximum intensity category
max_sustained_windnumberMaximum sustained winds (knots)
min_mslpnumberMinimum sea-level pressure (hPa)
dates_activeobjectStart and end dates
observed_trackarrayArray of observed positions
forecast_trackarrayArray of forecast positions
track[].category_codestringStorm category at position
track[].max_sustained_windnumberSustained wind speed (knots)
track[].min_mslpnumberCentral pressure (hPa)
track[].wind_extent_radiiobjectWind Radii at 34/50/64 kt in NE/SE/NW/SW quadrants (nautical miles)

Tidal Extrema Response

Response format for tidal extrema endpoint. Results are grouped by date; each entry lists every high and every low tide within that calendar day (usually two of each).

{
  "meta": {
    "unit_system": "si",
    "units": "m",
    "message": null
  },
  "data": [
    {
      "high": [
        { "time": "2024-01-15T03:24:00", "values": { "tide_height": 1.52 } },
        { "time": "2024-01-15T15:50:00", "values": { "tide_height": 1.31 } }
      ],
      "low": [
        { "time": "2024-01-15T09:47:00", "values": { "tide_height": -0.35 } },
        { "time": "2024-01-15T22:10:00", "values": { "tide_height": -0.61 } }
      ],
      "date": "2024-01-15"
    }
  ]
}

Schema

FieldTypeDescription
meta.unit_systemstringUnit system (si or us)
meta.unitsstringHeight unit (m or ft)
data[].datestringCalendar date
data[].high[]arrayHigh tides on that date
data[].high[].timestringTime of the high tide
data[].high[].values.tide_heightnumberHeight relative to MSL (Tidal Datum)
data[].low[]arrayLow tides on that date, same structure

Job Response

Response for asynchronous job submissions.

{
  "job_uuid": "601510c9-6402-4671-a3b0-a4b1a995e952",
  "job_type": "RouteRetrievalJob",
  "job_status": "initiated",
  "creation_time": "2026-09-21T14:44:45.558380+00:00",
  "export_uri": "https://api.wx.spire.com/export/601510c9-6402-4671-a3b0-a4b1a995e952"
}

The same object is returned by the status endpoint. Soil-moisture historical jobs return job_uuid and job_status only.

Status Values

Archive jobs progress through multiple stages; the API returns the values in lower case.

StatusDescription
createdJob submitted, queued for processing
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
unknownStatus could not be determined

Error Response

Errors are JSON and come in three shapes.

Subscription (entitlement) errors, HTTP 403. The message lists the values your key may use:

{
  "detail": "param: regions requested: ['north_america'] -- allowed: ['global', 'europe', 'conus'] -- unallowed: ['north_america']"
}

Validation errors, HTTP 422. One entry per problem, with the location of the offending parameter:

{
  "detail": [
    {
      "type": "missing",
      "loc": ["query", "end_datetime"],
      "msg": "Field required",
      "input": null
    }
  ]
}

Service errors, HTTP 404, 412 or 422:

{
  "message": "No data found matching the request"
}
HTTP statusMeaning
401Invalid or missing API key
403Product, bundle, region or time bundle not in your subscription
404Endpoint unknown, or no data matches the request
412Parameters that must be given together were given separately
422Invalid parameter value or missing required parameter
429Rate limit exceeded
500Server error

Python Data Classes

from dataclasses import dataclass
from typing import List, Optional
from datetime import datetime

@dataclass
class Coordinates:
    lat: float
    lon: float
    elevation: Optional[float] = None

@dataclass
class Location:
    coordinates: Coordinates

@dataclass
class Times:
    issuance_time: datetime
    valid_time: datetime

@dataclass
class ForecastRecord:
    location: Location
    times: Times
    values: dict

@dataclass
class ForecastResponse:
    meta: dict
    data: List[ForecastRecord]

def parse_forecast_response(json_data: dict) -> ForecastResponse:
    """Parse JSON response into typed data structure."""
    records = []
    for item in json_data['data']:
        record = ForecastRecord(
            location=Location(
                coordinates=Coordinates(
                    lat=item['location']['coordinates']['lat'],
                    lon=item['location']['coordinates']['lon'],
                    elevation=item['location']['coordinates'].get('elevation')
                )
            ),
            times=Times(
                issuance_time=datetime.fromisoformat(item['times']['issuance_time']),
                valid_time=datetime.fromisoformat(item['times']['valid_time'])
            ),
            values=item['values']
        )
        records.append(record)

    return ForecastResponse(
        meta=json_data['meta'],
        data=records
    )