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¶
| Field | Type | Description |
|---|---|---|
meta | object | Response metadata |
meta.unit_system | string | Unit system used: si, us or us-f |
meta.forecast | string | Product name, e.g. Spire SOF-D Forecast, Spire Optimized Point Forecast, Spire Current Weather Conditions |
meta.units | object | Unit of every field that can appear in values |
data | array | Array of forecast records |
data[].location | object | Location information |
data[].location.coordinates.lat | number | Latitude |
data[].location.coordinates.lon | number | Longitude |
data[].location.coordinates.elevation | number | Model terrain elevation at the grid point, metres above sea level |
data[].times | object | Temporal information |
data[].times.issuance_time | string | Forecast model run time (Issuance Time) |
data[].times.valid_time | string | Forecast Valid Time |
data[].times.requested_valid_time | string | Route endpoint only: the waypoint time you asked for |
data[].values | object | Weather 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¶
| Field | Type | Description |
|---|---|---|
meta | object | Response metadata |
meta.count | integer | Number of files |
meta.issuance_time | string | Forecast file listings only: the issuance the files belong to |
meta.message | string | Optional human-readable note |
files | array | List 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¶
| Field | Type | Required | Description |
|---|---|---|---|
route | object | Yes | Route definition |
route.name | string | No | Name for the route (used in archive output file names) |
route.waypoints | array | Yes | Array of waypoints (max 120 for forecast and insights routes, 10,000 for archive routes) |
route.waypoints[].lat | number | Yes | Latitude |
route.waypoints[].lon | number | Yes | Longitude |
route.waypoints[].time | string | Yes | ISO 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¶
| Field | Type | Description |
|---|---|---|
atcf_id | string | ATCF ID storm identifier |
storm_name | string | Storm name (empty until named) |
basin | string | Ocean basin code |
subbasin | string | Sub-basin code |
season | integer | Storm season year |
is_active | boolean | Whether storm is currently active |
max_development_category | string | Maximum intensity category |
max_sustained_wind | number | Maximum sustained winds (knots) |
min_mslp | number | Minimum sea-level pressure (hPa) |
dates_active | object | Start and end dates |
observed_track | array | Array of observed positions |
forecast_track | array | Array of forecast positions |
track[].category_code | string | Storm category at position |
track[].max_sustained_wind | number | Sustained wind speed (knots) |
track[].min_mslp | number | Central pressure (hPa) |
track[].wind_extent_radii | object | Wind 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¶
| Field | Type | Description |
|---|---|---|
meta.unit_system | string | Unit system (si or us) |
meta.units | string | Height unit (m or ft) |
data[].date | string | Calendar date |
data[].high[] | array | High tides on that date |
data[].high[].time | string | Time of the high tide |
data[].high[].values.tide_height | number | Height relative to MSL (Tidal Datum) |
data[].low[] | array | Low 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.
| Status | Description |
|---|---|
created | Job submitted, queued for processing |
restoring_files | Retrieving archived data from storage |
restore_completed | Archived data retrieved, ready for extraction |
initiated | Extraction process initiated |
processing | Data extraction in progress |
completed | Data ready for download |
failed | Job failed |
unknown | Status 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 status | Meaning |
|---|---|
401 | Invalid or missing API key |
403 | Product, bundle, region or time bundle not in your subscription |
404 | Endpoint unknown, or no data matches the request |
412 | Parameters that must be given together were given separately |
422 | Invalid parameter value or missing required parameter |
429 | Rate limit exceeded |
500 | Server 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
)