@mostlyrightmd/weather
Interfaces
Section titled “Interfaces”AlertsOptions
Section titled “AlertsOptions”Extends
Section titled “Extends”FetchWithRetryOptions
Properties
Section titled “Properties”
optionalarea:string
Two-letter state / marine area code, e.g. "TX".
event?
Section titled “event?”
optionalevent:string
NWS event name, e.g. "Hurricane Warning". Live route only — the archive
serves VTEC codes and no event name, so combining this with
source: "iem" throws ContractError naming phenomena/significance
as the replacement rather than filtering every row away.
fromTime?
Section titled “fromTime?”
optionalfromTime:string
Window start, ISO-8601 with a Z offset.
limit?
Section titled “limit?”
optionallimit:number
Page size for the live route.
phenomena?
Section titled “phenomena?”
optionalphenomena:string
VTEC phenomena code, e.g. "HU". Both routes.
significance?
Section titled “significance?”
optionalsignificance:string
VTEC significance code, e.g. "W". Both routes.
source?
Section titled “source?”
optionalsource:AlertsSource
Which route answers. Default "nws" (the live CAP feed).
toTime?
Section titled “toTime?”
optionaltoTime:string
Window end, ISO-8601 with a Z offset.
vintages?
Section titled “vintages?”
optionalvintages:Vintages
Row selector. Default "all". See Vintages.
optionalwfo:string
Forecast office, e.g. "MLB". Both routes: it narrows the archive query
server-side, and filters the decomposed wfo column on the live route.
optionalzone:string
UGC zone/county code, e.g. "TXZ213".
BestTrackOptions
Section titled “BestTrackOptions”Extends
Section titled “Extends”FetchWithRetryOptions
Properties
Section titled “Properties”filename?
Section titled “filename?”
optionalfilename:string
Read one exact upstream file name, bypassing revision selection.
revision?
Section titled “revision?”
optionalrevision:string
Read a named reanalysis vintage, as YYYY-MM-DD. HURDAT2 is re-analysed
annually and several revisions of the same season coexist, so pinning this
is what keeps a point-in-time research read from “predicting” an old storm
with values that did not exist until years later. Unset reads the newest
revision.
vintages?
Section titled “vintages?”
optionalvintages:Vintages
Row selector. Default "all". See Vintages.
BestTrackRevision
Section titled “BestTrackRevision”One HURDAT2 reanalysis file.
bestTrackRevisions() enumerates files rather than rows, which is why it is
the one verb in this family that does not return a DataResult: there is no
row grain and no schema id to stamp. Pass a filename or a revision back
into bestTrack() to read one.
Ordered ascending by revision, never by file name — the two orders
disagree, because the date encoding in the name is six digits in some years
and eight in others.
Properties
Section titled “Properties”basin:
"atl"|"nepac"
The file this revision belongs to: "atl" or "nepac". Pass it straight
back to BestTrackRevisionsOptions.basin. Not the storm-id
vocabulary — the nepac file holds both EP and CP storms.
filename
Section titled “filename”filename:
string
The exact upstream file name — part of the vintage identity.
revision
Section titled “revision”revision:
string
Revision date parsed out of the file name, as YYYY-MM-DD.
BestTrackRevisionsOptions
Section titled “BestTrackRevisionsOptions”Extends
Section titled “Extends”FetchWithRetryOptions
Properties
Section titled “Properties”basin?
Section titled “basin?”
optionalbasin:"atl"|"nepac"
Which published file to list: "atl" (Atlantic) or "nepac" (north-east
Pacific, which holds both the EP and CP storm-id prefixes). Default
"atl", matching Python’s best_track_revisions(basin="atl").
This is the file vocabulary, not the storm-id vocabulary: the nepac file
holds two storm-id prefixes, so the two cannot be the same word. An
unrecognised value throws ContractError before any request.
DailyExtremeRow
Section titled “DailyExtremeRow”One station-local day’s rollup.
Field names mirror Python DailyExtreme TypedDict exactly so
cross-language code reads the same way:
date,station,low_f,high_f,mean_f,precip_inlow_coverage(boolean) andobservation_count(int) for debug-friendly gating
Properties
Section titled “Properties”date:
string
Station-local calendar date as YYYY-MM-DD.
high_c
Section titled “high_c”high_c:
null|number
Maximum temperature in °C, or null on low coverage.
high_f
Section titled “high_f”high_f:
null|number
Maximum temperature in °F, or null on low coverage.
low_c:
null|number
Minimum temperature in °C, or null on low coverage. This is the
settlement-correct quantity Polymarket resolves on (the Python
daily_extremes label is Celsius, daily_extremes_low_c).
low_coverage
Section titled “low_coverage”low_coverage:
boolean
True when observation_count < 12 (matches Python low-coverage gate).
low_f:
null|number
Minimum temperature in °F, or null on low coverage.
mean_c
Section titled “mean_c”mean_c:
null|number
Mean temperature in °C, or null on low coverage.
mean_f
Section titled “mean_f”mean_f:
null|number
Mean temperature in °F, or null on low coverage.
observation_count
Section titled “observation_count”observation_count:
number
Count of observation rows that contributed to the day.
precip_in
Section titled “precip_in”precip_in:
null|number
Total 1-hour precipitation across the local day, in inches.
source_high
Section titled “source_high”source_high:
null|string
Source identifier of the row that produced tmax (null on low coverage).
source_low
Section titled “source_low”source_low:
null|string
Source identifier of the row that produced tmin (null on low coverage).
station
Section titled “station”station:
string
ICAO station code.
DailyExtremesOptions
Section titled “DailyExtremesOptions”Properties
Section titled “Properties”merge?
Section titled “merge?”
optionalmerge:DailyExtremesMergeMode
Source merge mode; default "live_v1".
signal?
Section titled “signal?”
optionalsignal:AbortSignal
Caller abort signal, propagated to every IEM/AWC fetch (and composed with
each attempt’s retry backoff wait). An abort mid-flight rejects promptly
with the platform AbortError — never reclassified as a transport error.
DailySummaryObservation
Section titled “DailySummaryObservation”Properties
Section titled “Properties”high_temp_f
Section titled “high_temp_f”high_temp_f:
null|number
Daily high °F, rounded to int. null when missing or out-of-bounds.
issued_at
Section titled “issued_at”issued_at:
null|string
ISO 8601 UTC issuance time parsed from product[:12], else null.
low_temp_f
Section titled “low_temp_f”low_temp_f:
null|number
Daily low °F, rounded to int. null when missing or out-of-bounds.
observation_date
Section titled “observation_date”observation_date:
string
Local climate day, YYYY-MM-DD.
product_id
Section titled “product_id”product_id:
null|string
Raw NWS product identifier when present.
report_type
Section titled “report_type”report_type:
ReportType
Inferred report type.
report_type_priority
Section titled “report_type_priority”report_type_priority:
number
Numeric priority for dedup (final=3, ncei_final=2.5, correction=2,
preliminary=1, estimated=0). Sourced from
CLIMATE_REPORT_TYPE_PRIORITY in @mostlyrightmd/core codegen.
source
Section titled “source”source:
"iem"
Always "iem" for CLI records.
station_code
Section titled “station_code”station_code:
string
Station code (3-letter NWS or 4-letter ICAO, caller’s choice).
ForecastNwpOptions
Section titled “ForecastNwpOptions”Optional knobs for forecastNwp.
Properties
Section titled “Properties”cycle?
Section titled “cycle?”
readonlyoptionalcycle:string
Model run datetime — UTC ISO string.
forecastHour?
Section titled “forecastHour?”
readonlyoptionalforecastHour:number
Forecast hour ahead of cycle.
member?
Section titled “member?”
readonlyoptionalmember:string
Ensemble member id (e.g. GEFS "p05", CFS "03"). Only meaningful for
GEFS and CFS.
GaugesOptions
Section titled “GaugesOptions”Options for gauges().
EXACTLY ONE of bbox or gaugeId is required. The two scopes answer differently when there is nothing to return — an empty box is an empty result, an unknown identifier throws — so which one was meant is never inferred, and passing both or neither throws before any request.
Extends
Section titled “Extends”FetchWithRetryOptions
Properties
Section titled “Properties”
optionalbbox:GaugeBbox
Enumerate the gauge INVENTORY inside this box. Split into tiles no wider than maxTileDegrees on either axis, because the route serves no paging and its unfiltered answer was measured at 13 MB and a gateway timeout. An inverted, zero-width, or off-the-globe box throws before any request.
gaugeId?
Section titled “gaugeId?”
optionalgaugeId:string
Return the ONE detail row for a single gauge: an NWS Location ID
("ABBG1") or a bare USGS site number ("02215260"). The route accepts
both on the same path and was measured answering identically, which is why
there is one option rather than two. The value is echoed back into the
row’s gauge_id column, so a flood frame joins on the identifier the
caller already holds.
maxTileDegrees?
Section titled “maxTileDegrees?”
optionalmaxTileDegrees:number
Widest tile a single request covers, in the units of srid.
optionalsrid:string
Spatial reference of the bbox corners. Always sent: the route
answers a missing or unrecognised projection with HTTP 200 and an EMPTY
gauge list, which reads as “no gauges here”. Default "EPSG_4326".
HazardAlertV1
Section titled “HazardAlertV1”Properties
Section titled “Properties”alert_id
Section titled “alert_id”alert_id:
string
primary key, unique per issuance. Live rows carry the CAP properties.id (‘urn:oid:…’); archive rows carry the deterministic ‘iem:{product_id}:{ugc_zone}’ so the two legs never collide and the archive leg is reproducible
area_description?
Section titled “area_description?”
optionalarea_description:null|string
CAP areaDesc: the human-readable zone list
captured_at
Section titled “captured_at”captured_at:
string
PROVENANCE STAMP: when the SDK captured this row. Not an event time, which is why it carries no _at_utc suffix. The vintage dedup key, so it is never null
certainty?
Section titled “certainty?”
optionalcertainty:null|string
effective_at_utc?
Section titled “effective_at_utc?”
optionaleffective_at_utc:null|string
CAP effective: when the alert takes force. Archive leg: utc_issue
ends_at_utc?
Section titled “ends_at_utc?”
optionalends_at_utc:null|string
CAP ends: when the hazard itself ends. Archive leg: utc_init_expire
event?
Section titled “event?”
optionalevent:null|string
NWS event name (‘Hurricane Warning’); one of 111 in /alerts/types
event_tracking_number?
Section titled “event_tracking_number?”
optionalevent_tracking_number:null|number
VTEC ETN; unique per (office, phenomena, significance, vtec_year)
expires_at_utc?
Section titled “expires_at_utc?”
optionalexpires_at_utc:null|string
CAP expires: when this issuance stops being current. Archive leg: utc_expire
headline?
Section titled “headline?”
optionalheadline:null|string
message_type?
Section titled “message_type?”
optionalmessage_type:null|string
CAP messageType: Alert | Update | Cancel | Ack | Error
onset_at_utc?
Section titled “onset_at_utc?”
optionalonset_at_utc:null|string
EVENT TIME: when the hazard itself begins. Archive leg: null (the watchwarn archive serves no separate onset)
phenomena?
Section titled “phenomena?”
optionalphenomena:null|string
VTEC phenomena code (HU = hurricane, FF = flash flood, FW = fire weather)
product_id?
Section titled “product_id?”
optionalproduct_id:null|string
AFOS product id (‘202410081215-KMLB-WHUS72-MWWMLB’); joins to the text product
raw_cap?
Section titled “raw_cap?”
optionalraw_cap:null|string
verbatim CAP ‘properties’ object as JSON, for re-parse provenance. Populated on nws.alerts.live rows only
raw_csv?
Section titled “raw_csv?”
optionalraw_csv:null|string
verbatim IEM watchwarn CSV record line, for re-parse provenance. Populated on iem.vtec.archive rows only
references?
Section titled “references?”
optionalreferences:null|string
JSON array of the alert_id values this issuance supersedes, in served order — a supersession EDGE, never a delete. Null when this is the first issuance of the event
sender_name?
Section titled “sender_name?”
optionalsender_name:null|string
sent_at_utc?
Section titled “sent_at_utc?”
optionalsent_at_utc:null|string
KNOWLEDGE TIME: when NWS issued this alert — the instant it became knowable. align() cuts on this column. Archive leg: utc_prodissue
severity?
Section titled “severity?”
optionalseverity:null|string
significance?
Section titled “significance?”
optionalsignificance:null|string
VTEC significance code (W = warning, A = watch, Y = advisory, S = statement)
source
Section titled “source”source:
string
per-row source identity == df.attrs[‘source’]
ugc_zone
Section titled “ugc_zone”ugc_zone:
string
UGC zone/county code (FLC086); the second half of the row identity
urgency?
Section titled “urgency?”
optionalurgency:null|string
vtec_action?
Section titled “vtec_action?”
optionalvtec_action:null|string
VTEC action: NEW | CON | CAN | EXP | EXT | UPG — the supersession verb
vtec_class?
Section titled “vtec_class?”
optionalvtec_class:null|string
VTEC product class: O (operational) | T (test) | E (exercise) | X
vtec_office?
Section titled “vtec_office?”
optionalvtec_office:null|string
VTEC 4-letter office id (KPSR); the archive’s 3-letter wfo drops the K/P
vtec_string?
Section titled “vtec_string?”
optionalvtec_string:null|string
the verbatim VTEC string, e.g. ‘/O.CON.KPSR.XH.W.0007.000000T0000Z-260804T0300Z/’. Kept beside the decomposed columns so a re-parse is always possible
vtec_year?
Section titled “vtec_year?”
optionalvtec_year:null|number
year the ETN sequence belongs to; the archive returns it as a column
optionalwfo:null|string
3-letter forecast office (PSR); the archive leg’s own spelling
HazardBestTrackV1
Section titled “HazardBestTrackV1”Properties
Section titled “Properties”basin:
string
AL | EP | CP, from the storm_id prefix
captured_at
Section titled “captured_at”captured_at:
string
PROVENANCE STAMP: when the SDK captured this row (the vintage dedup key)
hurdat2_filename
Section titled “hurdat2_filename”hurdat2_filename:
string
the exact upstream filename (‘hurdat2-1851-2025-02272026.txt’); there is no stable ‘latest’ alias, so the filename is part of the vintage identity
hurdat2_revision
Section titled “hurdat2_revision”hurdat2_revision:
string
KNOWLEDGE TIME: the reanalysis vintage date parsed out of the HURDAT2 filename — the date these values became knowable, NOT the date of the fix
landfall_flag?
Section titled “landfall_flag?”
optionallandfall_flag:null|string
HURDAT2 record identifier; ‘L’ marks a LANDFALL fix — the settlement-relevant flag for ‘hurricane hits X’ contracts
latitude
Section titled “latitude”latitude:
number
units: degrees_north
longitude
Section titled “longitude”longitude:
number
units: degrees_east
max_wind_kt?
Section titled “max_wind_kt?”
optionalmax_wind_kt:null|number
units: kt — HURDAT2 serves -999 for missing; the parser maps that to null
min_pressure_mb?
Section titled “min_pressure_mb?”
optionalmin_pressure_mb:null|number
units: hPa — HURDAT2 serves -999 for missing; the parser maps that to null
radius_max_wind_nm?
Section titled “radius_max_wind_nm?”
optionalradius_max_wind_nm:null|number
units: nmi
raw_hurdat2
Section titled “raw_hurdat2”raw_hurdat2:
string
verbatim HURDAT2 record line, for re-parse provenance
source
Section titled “source”source:
string
per-row source identity == df.attrs[‘source’]
status
Section titled “status”status:
string
system status: TD | TS | HU | EX | SD | SS | LO | WV | DB
storm_id
Section titled “storm_id”storm_id:
string
HURDAT2 header id (AL142024); the per-entity join key
storm_name?
Section titled “storm_name?”
optionalstorm_name:null|string
valid_at_utc
Section titled “valid_at_utc”valid_at_utc:
string
EVENT TIME: the synoptic fix time (HURDAT2 YYYYMMDD + HHMM)
wind_radii_nm?
Section titled “wind_radii_nm?”
optionalwind_radii_nm:null|string
units: nmi — the 12 quadrant wind-radii fields as a JSON array string in HURDAT2 order; missing values are JSON null
HazardGaugeV1
Section titled “HazardGaugeV1”Properties
Section titled “Properties”action_flow_cfs?
Section titled “action_flow_cfs?”
optionalaction_flow_cfs:null|number
units: cfs — cubic feet per second, the unit this route already serves. The stage-and-flow route serves KILO-cubic-feet per second for the same gauge, so only that product’s flow_cfs column is comparable to this one
action_stage_ft?
Section titled “action_stage_ft?”
optionalaction_stage_ft:null|number
units: ft — NULL when the upstream serves its no-threshold encoding
captured_at
Section titled “captured_at”captured_at:
string
PROVENANCE STAMP: when the SDK captured this row. Also this schema’s knowledge time and event time, because gauge reference data carries no upstream issuance stamp. Part of the dedup key, so it is never null
county?
Section titled “county?”
optionalcounty:null|string
forecast_flood_category?
Section titled “forecast_flood_category?”
optionalforecast_flood_category:null|string
the same categorization for the current forecast. Roughly one gauge in four carries a current forecast at any moment; the rest read fcst_not_current
gauge_id
Section titled “gauge_id”gauge_id:
string
the identifier the caller passed, echoed on every row of every flood product so a water frame and a gauge frame join on ONE column. On the NWPS leg it equals nws_location_id; both columns are still present so a caller never has to know which namespace a frame came from. No code path synthesizes a merged id
in_service?
Section titled “in_service?”
optionalin_service:null|boolean
the upstream inService flag; NULL on an inventory row
latitude?
Section titled “latitude?”
optionallatitude:null|number
units: degrees_north
longitude?
Section titled “longitude?”
optionallongitude:null|number
units: degrees_east
major_flow_cfs?
Section titled “major_flow_cfs?”
optionalmajor_flow_cfs:null|number
units: cfs
major_stage_ft?
Section titled “major_stage_ft?”
optionalmajor_stage_ft:null|number
units: ft
minor_flow_cfs?
Section titled “minor_flow_cfs?”
optionalminor_flow_cfs:null|number
units: cfs
minor_stage_ft?
Section titled “minor_stage_ft?”
optionalminor_stage_ft:null|number
units: ft
moderate_flow_cfs?
Section titled “moderate_flow_cfs?”
optionalmoderate_flow_cfs:null|number
units: cfs
moderate_stage_ft?
Section titled “moderate_stage_ft?”
optionalmoderate_stage_ft:null|number
units: ft
monitoring_location_id?
Section titled “monitoring_location_id?”
optionalmonitoring_location_id:null|string
the same site number as usgs_site_id in USGS’s own prefixed spelling (USGS-02215260). Both are carried because the two upstreams address the same station differently
optionalname:null|string
nws_location_id
Section titled “nws_location_id”nws_location_id:
string
the five-character NWS Location ID (ABBG1) the upstream calls ‘lid’
observed_flood_category?
Section titled “observed_flood_category?”
optionalobserved_flood_category:null|string
the NWS categorization of the current observed value: no_flooding | action | minor | moderate | major | low_threshold | not_defined | obs_not_current | out_of_service
raw_json
Section titled “raw_json”raw_json:
string
the verbatim upstream gauge object as JSON, for re-parse provenance. Every field this schema does not type — including the upstream unit strings and the free-text impact statements — survives here
reach_id?
Section titled “reach_id?”
optionalreach_id:null|string
the National Water Model reach identifier, when the gauge has one
record_scope
Section titled “record_scope”record_scope:
"detail"|"inventory"
which route produced the row. ‘inventory’ rows come from the gauge LIST route, which serves no usgsId, no reachId, no flood thresholds and no timeZone — so on an inventory row those columns are NULL because the ROUTE omits them, not because the gauge lacks them. Roughly two gauges in three carry a USGS site number and three in four carry a reach id, so both readings of a NULL are common and the discriminator is what separates them
optionalrfc:null|string
the River Forecast Center abbreviation that issues for this gauge
source
Section titled “source”source:
string
per-row source identity == df.attrs[‘source’]
state?
Section titled “state?”
optionalstate:null|string
thresholds_defined
Section titled “thresholds_defined”thresholds_defined:
boolean
True if and only if all four *_stage_ft values are non-NULL after missing-value normalization. Measured coverage across a 60-gauge sample: 10% had all four stage AND all four flow thresholds, and 47% had no stage thresholds at all — so a threshold comparison without this column reads ‘not flooding’ for a gauge that simply has nothing to compare against
timezone?
Section titled “timezone?”
optionaltimezone:null|string
the upstream timezone string, VERBATIM. It is a POSIX-style spelling and four of the eight distinct values observed across a gauge sample do not exist in tzdata — one of them pairs Eastern standard time with Central daylight time. It is never replaced by a guess; read timezone_loadable before using it
timezone_loadable
Section titled “timezone_loadable”timezone_loadable:
boolean
True when zoneinfo loads the timezone string above. Carried as DATA so an unusable zone costs a caller one column read instead of an exception on a gauge whose stage readings are fine
usgs_site_id?
Section titled “usgs_site_id?”
optionalusgs_site_id:null|string
the bare USGS site number (02215260). NULL on an inventory row because that route omits it, and NULL on a detail row when the gauge genuinely has none — read record_scope to tell which
optionalwfo:null|string
HazardHotspotV1
Section titled “HazardHotspotV1”Properties
Section titled “Properties”acquired_at_utc
Section titled “acquired_at_utc”acquired_at_utc:
string
EVENT TIME: the overpass instant. Built from the upstream date plus its zero-padded four-character time-of-day string, which is never read as an integer — that would turn an overpass just after midnight into one just after seven in the morning
attribution
Section titled “attribution”attribution:
string
the acknowledgment the provider requires, on EVERY row. It is a column rather than frame metadata because concat, merge, and groupby all drop df.attrs, and an acknowledgment that disappears on the first join is not an acknowledgment
brightness_k?
Section titled “brightness_k?”
optionalbrightness_k:null|number
units: K — the primary channel brightness temperature. Which physical channel that is depends on sensor_family, which is why the column is named for its role rather than for one family’s channel number
brightness_secondary_k?
Section titled “brightness_secondary_k?”
optionalbrightness_secondary_k:null|number
units: K — the second channel’s brightness temperature, on the same rule
captured_at
Section titled “captured_at”captured_at:
string
PROVENANCE STAMP and KNOWLEDGE TIME: when the SDK captured this row. Deliberately later than acquired_at_utc — the overpass instant is when the fire burned, and publication lags it by hours. The vintage dedup key, so it is never null
confidence_category?
Section titled “confidence_category?”
optionalconfidence_category:null|"high"|"low"|"nominal"
the imaging-radiometer family’s confidence, which the upstream reports as a word. NULL on the other family. A single ‘confidence at least x’ filter cannot span both dialects, which is exactly why they are two columns
confidence_percent?
Section titled “confidence_percent?”
optionalconfidence_percent:null|number
units: percent — the spectroradiometer family’s confidence, which the upstream reports as a percent from 0 to 100. NULL on the other family
detection_type?
Section titled “detection_type?”
optionaldetection_type:null|string
the upstream inferred-type code, which distinguishes a vegetation fire from a volcano, a static land source, and an offshore detection. Served on the archive product only, so it is NULL on a near-real-time row
fire_radiative_power_mw?
Section titled “fire_radiative_power_mw?”
optionalfire_radiative_power_mw:null|number
units: MW — radiative power of the detected fire
is_daytime?
Section titled “is_daytime?”
optionalis_daytime:null|boolean
whether the overpass was on the day side. The upstream spells this as a one-letter string; a two-valued flag stored that way is a filter every caller has to write twice
latitude
Section titled “latitude”latitude:
number
units: degrees_north
longitude
Section titled “longitude”longitude:
number
units: degrees_east
pixel_scan_km?
Section titled “pixel_scan_km?”
optionalpixel_scan_km:null|number
units: km — the along-scan ground dimension of the detection pixel. The upstream header spells this one word with no unit, which is unreadable out of context; the token itself survives in raw_csv
pixel_track_km?
Section titled “pixel_track_km?”
optionalpixel_track_km:null|number
units: km — the along-track ground dimension of the detection pixel. The upstream one-word spelling is not used here because the same word already names a hurricane best track in this schema family
product_version
Section titled “product_version”product_version:
string
the upstream processing version. Standard-quality data replaces the near-real-time product after roughly three months, so this is a vintage attribute: the SAME overpass yields a different row depending on when it was fetched
raw_csv
Section titled “raw_csv”raw_csv:
string
the verbatim upstream CSV record line, for re-parse provenance. Every upstream header token this schema renames survives here
region?
Section titled “region?”
optionalregion:null|string
the bulk file’s region token. NULL on the bounding-box route, which has no region — read the coordinates instead
satellite
Section titled “satellite”satellite:
string
the upstream platform token VERBATIM (N, N20, N21, A, T)
sensor_family
Section titled “sensor_family”sensor_family:
"modis"|"viirs"
which instrument family produced the row. It decides the brightness channels, the pixel footprint, and — see below — which of the two confidence columns is populated
source
Section titled “source”source:
string
per-row source identity == df.attrs[‘source’]
window?
Section titled “window?”
optionalwindow:null|string
the bulk file’s look-back window token. NULL on the bounding-box route, which takes a day count instead
HazardRatingCurveV1
Section titled “HazardRatingCurveV1”Properties
Section titled “Properties”captured_at
Section titled “captured_at”captured_at:
string
PROVENANCE STAMP: when the SDK captured this row. Also this schema’s knowledge time and event time — a rating curve carries no upstream publication stamp
flow_cfs
Section titled “flow_cfs”flow_cfs:
number
units: cfs — the discharge this curve maps that stage to, in cubic feet per second
gauge_id
Section titled “gauge_id”gauge_id:
string
the identifier the caller passed; joins to schema.hazard.gauge.v1
nws_location_id?
Section titled “nws_location_id?”
optionalnws_location_id:null|string
the NWS Location ID this curve belongs to. NULL when the caller addressed the gauge by its USGS site number — same reason as schema.hazard.stage_and_flow.v1’s column of this name: the ratings route takes either namespace and returns no lid
raw_json
Section titled “raw_json”raw_json:
string
the verbatim upstream curve point as JSON, for re-parse provenance
source
Section titled “source”source:
string
per-row source identity == df.attrs[‘source’]
stage_ft
Section titled “stage_ft”stage_ft:
number
units: ft — the curve’s independent variable; part of the row identity
HazardStageAndFlowV1
Section titled “HazardStageAndFlowV1”Properties
Section titled “Properties”captured_at
Section titled “captured_at”captured_at:
string
PROVENANCE STAMP: when the SDK captured this row. Part of the dedup key because only one forecast issuance is ever served — an uncaptured issuance cannot be fetched again
flow_cfs?
Section titled “flow_cfs?”
optionalflow_cfs:null|number
units: cfs — flow_kcfs converted through the one shared unit table. The ONLY flow column comparable to schema.hazard.gauge.v1’s *_flow_cfs thresholds and to schema.hazard.rating_curve.v1
flow_kcfs?
Section titled “flow_kcfs?”
optionalflow_kcfs:null|number
units: kcfs — the VERBATIM number this route serves, in kilo-cubic-feet per second. Comparing it to a gauge threshold in cubic feet per second is a thousandfold error; use flow_cfs for that
forecast_issued_at_utc?
Section titled “forecast_issued_at_utc?”
optionalforecast_issued_at_utc:null|string
KNOWLEDGE TIME on a forecast row: when the River Forecast Center issued this forecast. NULL on an observed row. A forecast row is never joinable to an observation date without it
gauge_id
Section titled “gauge_id”gauge_id:
string
the identifier the caller passed; joins to schema.hazard.gauge.v1
generated_at_utc?
Section titled “generated_at_utc?”
optionalgenerated_at_utc:null|string
the upstream production stamp, NOT a vintage key. It was measured four minutes later than the block issuance and is uniform across every point of one forecast block
latest_observation_at_utc?
Section titled “latest_observation_at_utc?”
optionallatest_observation_at_utc:null|string
KNOWLEDGE TIME on an observed row: the timestamp of the newest observation in the block the row came from. The upstream serves this in the SAME field it uses for the forecast issuance, but it is not an issuance — so it gets its own column. NULL on a forecast row
nws_location_id?
Section titled “nws_location_id?”
optionalnws_location_id:null|string
the NWS Location ID this series belongs to. NULL when the caller addressed the gauge by its USGS site number: this route accepts either namespace on the same path and its payload carries no lid, so there is no NWS Location ID to report. It is left NULL rather than filled with the site number, which would put a USGS identifier in a column whose name says NWS — read gauge_id for what the caller passed
raw_json
Section titled “raw_json”raw_json:
string
the verbatim upstream data point as JSON, for re-parse provenance. The block’s unit strings survive here
series
Section titled “series”series:
"forecast"|"observed"
which block of the upstream payload produced the row. Observed and forecast are never merged into one series: one is a measurement and the other is a prediction, and which of the two issuance columns below is populated depends on this value
shef_code?
Section titled “shef_code?”
optionalshef_code:null|string
the SHEF physical-element code identifying the series (HGIRG, HGIFF)
source
Section titled “source”source:
string
per-row source identity == df.attrs[‘source’]
stage_ft?
Section titled “stage_ft?”
optionalstage_ft:null|number
units: ft
timezone?
Section titled “timezone?”
optionaltimezone:null|string
the upstream timezone string verbatim; see schema.hazard.gauge.v1
valid_at_utc
Section titled “valid_at_utc”valid_at_utc:
string
EVENT TIME: the instant this stage or flow value describes
optionalwfo:null|string
HazardTextProductV1
Section titled “HazardTextProductV1”Properties
Section titled “Properties”advisory_number?
Section titled “advisory_number?”
optionaladvisory_number:null|string
kept as a STRING: NHC zero-pads it (‘032’) and intermediate advisories carry a letter suffix (‘15A’), so an integer column would lose both
amendment_suffix?
Section titled “amendment_suffix?”
optionalamendment_suffix:null|string
the ‘-AAA’ / ‘-BBB’ correction marker split off the product_id
awips_id?
Section titled “awips_id?”
optionalawips_id:null|string
AWIPS identifier (PSHLIX). ID-FIRST, on the same rule as wmo_id. The live route serves no AFOS id, so there it always comes from the bulletin
captured_at
Section titled “captured_at”captured_at:
string
PROVENANCE STAMP: when the SDK captured this row (the vintage dedup key)
issued_at_utc
Section titled “issued_at_utc”issued_at_utc:
string
KNOWLEDGE TIME and EVENT TIME: for a text bulletin the two instants coincide — the bulletin becomes knowable at the moment it is issued
issuing_office
Section titled “issuing_office”issuing_office:
string
issuing office id (KNHC, KLIX); the per-entity join key
parse_status
Section titled “parse_status”parse_status:
"parsed"|"raw_only"
‘raw_only’ when the free-text parse missed; raw_afos is still complete
product_code
Section titled “product_code”product_code:
string
AFOS product code: TCP | TCM | TCD | TCV | PSH
product_id
Section titled “product_id”product_id:
string
primary key, e.g. ‘202607301834-KLIX-ACUS74-PSHLIX-AAA’. The trailing amendment suffix is PART of the key
raw_afos
Section titled “raw_afos”raw_afos:
string
verbatim AFOS bulletin text, for re-parse provenance
source
Section titled “source”source:
string
per-row source identity == df.attrs[‘source’]
storm_id?
Section titled “storm_id?”
optionalstorm_id:null|string
NHC storm id (AL142024) when the bulletin names one; null for PSH-by-office
storm_name?
Section titled “storm_name?”
optionalstorm_name:null|string
wmo_id?
Section titled “wmo_id?”
optionalwmo_id:null|string
WMO product identifier (ACUS74). ID-FIRST: read from the AFOS product_id when it carries one, and from the bulletin’s WMO heading otherwise. The id is a strictly anchored parse of a value the archive guarantees; the heading is free text
HazardTropicalCycloneV1
Section titled “HazardTropicalCycloneV1”Properties
Section titled “Properties”advisory_number?
Section titled “advisory_number?”
optionaladvisory_number:null|string
zero-padded, may carry an intermediate suffix — a string, not an int
basin?
Section titled “basin?”
optionalbasin:null|string
AL | EP | CP, derived from the storm_id prefix
captured_at
Section titled “captured_at”captured_at:
string
PROVENANCE STAMP: when the SDK captured this row (the vintage dedup key)
classification?
Section titled “classification?”
optionalclassification:null|string
NHC classification: TD | TS | HU | PTC | STD | STS
forecast_advisory_url?
Section titled “forecast_advisory_url?”
optionalforecast_advisory_url:null|string
forecast_discussion_url?
Section titled “forecast_discussion_url?”
optionalforecast_discussion_url:null|string
intensity_kt?
Section titled “intensity_kt?”
optionalintensity_kt:null|number
units: kt — maximum sustained wind; NHC serves it as a quoted string
last_update_at_utc?
Section titled “last_update_at_utc?”
optionallast_update_at_utc:null|string
KNOWLEDGE TIME and EVENT TIME: NHC’s own lastUpdate stamp is both when the storm state was observed and when it became knowable
latitude?
Section titled “latitude?”
optionallatitude:null|number
units: degrees_north
longitude?
Section titled “longitude?”
optionallongitude:null|number
units: degrees_east
movement_direction_degrees?
Section titled “movement_direction_degrees?”
optionalmovement_direction_degrees:null|number
units: degrees
movement_speed_kt?
Section titled “movement_speed_kt?”
optionalmovement_speed_kt:null|number
units: kt
pressure_mb?
Section titled “pressure_mb?”
optionalpressure_mb:null|number
units: hPa — minimum central pressure; NHC serves it as a quoted string
public_advisory_url?
Section titled “public_advisory_url?”
optionalpublic_advisory_url:null|string
raw_json
Section titled “raw_json”raw_json:
string
verbatim NHC storm object as JSON, for re-parse provenance
source
Section titled “source”source:
string
per-row source identity == df.attrs[‘source’]
storm_id
Section titled “storm_id”storm_id:
string
NHC storm id (al142024 / ep072026); the per-entity join key
storm_name?
Section titled “storm_name?”
optionalstorm_name:null|string
HazardWaterObservationV1
Section titled “HazardWaterObservationV1”Properties
Section titled “Properties”approval_status?
Section titled “approval_status?”
optionalapproval_status:null|string
‘Provisional’ or ‘Approved’. The flip was measured between 60 and 90 days back, and it can change the VALUE, not only the label — which is why last_modified_at_utc is a dedup key rather than a display column
captured_at
Section titled “captured_at”captured_at:
string
PROVENANCE STAMP: when the SDK captured this row. Deliberately NOT part of this product’s dedup key — the upstream vintage already identifies the revision, so re-fetching is idempotent
gauge_id
Section titled “gauge_id”gauge_id:
string
the identifier the caller passed, echoed on every row so a water frame and a gauge frame join on one column instead of the caller choosing between three spellings of the same station
last_modified_at_utc
Section titled “last_modified_at_utc”last_modified_at_utc:
string
KNOWLEDGE TIME, and the UPSTREAM-PROVIDED vintage key: when USGS last revised this row. The legacy water-services host has no equivalent, which is why this schema does not accept it as a source. Because the vintage comes from upstream, re-fetching an unrevised row is idempotent
monitoring_location_id
Section titled “monitoring_location_id”monitoring_location_id:
string
the same site number in USGS’s own prefixed spelling (USGS-02215260)
parameter_code
Section titled “parameter_code”parameter_code:
string
the USGS parameter code (00065 = gage height, 00060 = discharge)
qualifier?
Section titled “qualifier?”
optionalqualifier:null|string
the upstream per-row qualifier code, when present
raw_json
Section titled “raw_json”raw_json:
string
the verbatim upstream feature properties as JSON, for re-parse provenance
source
Section titled “source”source:
string
per-row source identity == df.attrs[‘source’]
statistic_id?
Section titled “statistic_id?”
optionalstatistic_id:null|string
the USGS statistic code, when the series declares one
time_series_id
Section titled “time_series_id”time_series_id:
string
the upstream’s stable per-series identifier. Part of the dedup key, because one station serves several series and a derived site:parameter:statistic string would not distinguish two sensors on the same parameter
timezone_abbreviation?
Section titled “timezone_abbreviation?”
optionaltimezone_abbreviation:null|string
the station’s standard-time abbreviation. With the flag below it gives local standard time directly, needing no tz-database lookup
units_raw?
Section titled “units_raw?”
optionalunits_raw:null|string
the upstream unit string verbatim. Unlike the NWPS routes — whose units are fixed per route and therefore belong in raw_json — this table is multi-parameter, so the unit varies row to row and has to be a column
uses_daylight_saving_time?
Section titled “uses_daylight_saving_time?”
optionaluses_daylight_saving_time:null|boolean
whether the station observes daylight saving time
usgs_site_id
Section titled “usgs_site_id”usgs_site_id:
string
the bare USGS site number (02215260)
valid_at_utc
Section titled “valid_at_utc”valid_at_utc:
string
EVENT TIME: the instant this reading describes
value?
Section titled “value?”
optionalvalue:null|number
the reading, coerced from the quoted string the upstream serves. Its unit is in units_raw, because it varies per parameter_code on this one schema
HazardWildfireV1
Section titled “HazardWildfireV1”Properties
Section titled “Properties”acres?
Section titled “acres?”
optionalacres:null|number
units: acre — the currently reported size — the number that revises, and the reason this tier captures vintages at all
admin_unit?
Section titled “admin_unit?”
optionaladmin_unit:null|string
the administering unit; state leg only
agency_names?
Section titled “agency_names?”
optionalagency_names:null|string
captured_at
Section titled “captured_at”captured_at:
string
PROVENANCE STAMP and KNOWLEDGE TIME: when the SDK captured this row. The vintage dedup key, so it is never null. The live interagency service drops a fire once it is contained and after a size-dependent staleness window, so an uncaptured revision cannot be fetched again
cause?
Section titled “cause?”
optionalcause:null|string
cause_general?
Section titled “cause_general?”
optionalcause_general:null|string
complex_id?
Section titled “complex_id?”
optionalcomplex_id:null|string
complex_name?
Section titled “complex_name?”
optionalcomplex_name:null|string
complexity_level?
Section titled “complexity_level?”
optionalcomplexity_level:null|string
contained_at_utc?
Section titled “contained_at_utc?”
optionalcontained_at_utc:null|string
controlled_at_utc?
Section titled “controlled_at_utc?”
optionalcontrolled_at_utc:null|string
coordination_center?
Section titled “coordination_center?”
optionalcoordination_center:null|string
the expanded name of what gacc_code designates — a Geographic Area Coordination Center. Carried beside the abbreviation so a caller reading a column list does not have to look one up
county?
Section titled “county?”
optionalcounty:null|string
created_at_utc?
Section titled “created_at_utc?”
optionalcreated_at_utc:null|string
when the upstream record was created (interagency leg)
discovered_at_utc?
Section titled “discovered_at_utc?”
optionaldiscovered_at_utc:null|string
EVENT TIME: when the fire was discovered
discovery_acres?
Section titled “discovery_acres?”
optionaldiscovery_acres:null|number
units: acre — the size at discovery; interagency leg only
dispatch_center?
Section titled “dispatch_center?”
optionaldispatch_center:null|string
estimated_cost_to_date?
Section titled “estimated_cost_to_date?”
optionalestimated_cost_to_date:null|number
units: USD
final_acres?
Section titled “final_acres?”
optionalfinal_acres:null|number
units: acre — the certified size. Interagency leg only, and null long after a fire is out — the operational record is not revised once the fire report is closed
optionalfips:null|string
the county FIPS code as a STRING; leading zeros are significant
gacc_code?
Section titled “gacc_code?”
optionalgacc_code:null|string
the upstream coordination-centre token VERBATIM, because it is the join key and because a reader grepping the interagency documentation has to find it under the name it is published as
incident_id
Section titled “incident_id”incident_id:
string
primary key within one capture. The interagency leg carries the IRWIN incident GUID with its braces stripped; the state leg carries that feed’s own record UUID. The two namespaces never collide, so one physical fire seen by both feeds is two rows and the source column says which is which
incident_name?
Section titled “incident_name?”
optionalincident_name:null|string
incident_type?
Section titled “incident_type?”
optionalincident_type:null|string
the upstream incident category VERBATIM. The interagency feed mixes prescribed burns and incident complexes into every service, and the state feed mixes floods and hazardous-material responses into its list, so a caller summing acreage without reading this column counts intentional burns as wildfire
incident_url?
Section titled “incident_url?”
optionalincident_url:null|string
is_active?
Section titled “is_active?”
optionalis_active:null|boolean
the state feed’s own active flag; NULL on the interagency leg
is_complex_child?
Section titled “is_complex_child?”
optionalis_complex_child:null|boolean
true when this incident rolls up into a complex. A complex record and its children are all in the feed, so summing acreage without reading this column double-counts every child
is_final?
Section titled “is_final?”
optionalis_final:null|boolean
the state feed’s own final flag. It keeps moving after it turns true: the longest measured gap between a fire being declared extinguished and its record being modified again was 546 days
latitude?
Section titled “latitude?”
optionallatitude:null|number
units: degrees_north — state leg only. The interagency route is queried with geometry off, which is this tier’s hard constraint, so an interagency row carries no coordinates
longitude?
Section titled “longitude?”
optionallongitude:null|number
units: degrees_east
modified_at_utc?
Section titled “modified_at_utc?”
optionalmodified_at_utc:null|string
the upstream last-modified time; an ORDINARY column, never a vintage key. 9,098 of 14,587 out-fires in a year-to-date sample were modified more than a day after being declared out with the acreage frozen, so it records administrative churn rather than when a number became knowable
out_at_utc?
Section titled “out_at_utc?”
optionalout_at_utc:null|string
when the fire was declared out. On the state leg the upstream spells an absent value as an empty string rather than null; the parser folds both to NULL
percent_contained?
Section titled “percent_contained?”
optionalpercent_contained:null|number
units: percent
raw_esri?
Section titled “raw_esri?”
optionalraw_esri:null|string
verbatim upstream record in the format this column’s name declares (re-parse provenance): the interagency service’s attribute bag as JSON. Populated on the wfigs legs only
raw_json?
Section titled “raw_json?”
optionalraw_json:null|string
verbatim upstream record in the format this column’s name declares (re-parse provenance): the state feed’s own record as JSON. Populated on the calfire leg only
source
Section titled “source”source:
string
per-row source identity == df.attrs[‘source’]
state?
Section titled “state?”
optionalstate:null|string
the bare two-letter state code. The interagency feed spells it with a country prefix and the state feed does not; both legs reduce to the bare token so they join on this column, and the served spelling survives in the row’s raw column
total_personnel?
Section titled “total_personnel?”
optionaltotal_personnel:null|number
assigned personnel; the nullable integer dtype, so absent stays absent
unique_fire_identifier?
Section titled “unique_fire_identifier?”
optionalunique_fire_identifier:null|string
the interagency year + protecting-unit + local-identifier string; the stable cross-year join key when one exists
HotspotsOptions
Section titled “HotspotsOptions”Options for hotspots().
Extends
Section titled “Extends”FetchWithRetryOptions
Properties
Section titled “Properties”
optionalbbox:HotspotBbox
The area to read, ordered west, south, east, north.
REQUIRES source: "firms.area" and a key of your own: the bulk tier serves
fixed regional files, so honouring a box with one would return the wrong
geography under a right-looking call. Passing it without that source throws
and names both the source and the environment variable.
fromTime?
Section titled “fromTime?”
optionalfromTime:Date
Earliest overpass instant to keep. Given together with toTime or not at
all — one bound alone throws, because inventing the other decides which
overpasses come back. Both unset means the most recent published look-back.
The verb derives the upstream’s own window token from the pair and filters
the parsed rows to the requested span.
region?
Section titled “region?”
optionalregion:FirmsRegion
Which published region. Defaults to "usa". Refused with
source: "firms.area", which is addressed by bbox instead — silently
ignoring one of the two would return the wrong geography under a
right-looking call.
sensor?
Section titled “sensor?”
optionalsensor:FirmsSensor
Which platform. Defaults to "viirs_snpp".
source?
Section titled “source?”
optionalsource:HotspotSource
Which route answers. Unset means the keyless bulk tier.
toTime?
Section titled “toTime?”
optionaltoTime:Date
Latest overpass instant to keep. Given together with fromTime.
IemMosOptions
Section titled “IemMosOptions”Optional knobs for iemMosForecasts.
Properties
Section titled “Properties”fetchFn()?
Section titled “fetchFn()?”
readonlyoptionalfetchFn: (input,init?) =>Promise<Response>(input,init?) =>Promise<Response>
Override the fetch function (used by tests).
Parameters
Section titled “Parameters”URL | RequestInfo
RequestInit
Returns
Section titled “Returns”Promise<Response>
Parameters
Section titled “Parameters”string | URL | Request
RequestInit
Returns
Section titled “Returns”Promise<Response>
model?
Section titled “model?”
readonlyoptionalmodel:IemMosModel
Default "nbe".
signal?
Section titled “signal?”
readonlyoptionalsignal:AbortSignal
Caller abort signal. Propagated to every per-cycle fetch; an abort during
an in-flight request rejects promptly with the platform AbortError.
IemMosRow
Section titled “IemMosRow”One IEM MOS forecast row.
Properties
Section titled “Properties”dewPointC
Section titled “dewPointC”
readonlydewPointC:null|number
2-m dew point in Celsius.
forecastHour
Section titled “forecastHour”
readonlyforecastHour:number
(validAt - issuedAt) in hours.
issuedAt
Section titled “issuedAt”
readonlyissuedAt:string
Model run datetime — UTC ISO string.
readonlymodel:string
UPPERCASE model id (e.g. "NBE").
precipProbability
Section titled “precipProbability”
readonlyprecipProbability:null|number
12-hour probability of precipitation [0, 1].
retrievedAt
Section titled “retrievedAt”
readonlyretrievedAt:string
When the row was fetched — UTC ISO string.
skyCoverPct
Section titled “skyCoverPct”
readonlyskyCoverPct:null|number
Sky cover %; IEM MOS does not expose this — always null.
source
Section titled “source”
readonlysource:IemMosSource
Per-row source identity. Always "iem.archive" for now.
station
Section titled “station”
readonlystation:string
ICAO station code (uppercased).
readonlytempC:null|number
2-m temperature in Celsius (null when MOS field is M / missing).
validAt
Section titled “validAt”
readonlyvalidAt:string
Forecast valid datetime — UTC ISO string.
windDirDeg
Section titled “windDirDeg”
readonlywindDirDeg:null|number
Wind direction in degrees [0, 360).
windSpeedMs
Section titled “windSpeedMs”
readonlywindSpeedMs:null|number
10-m wind speed in m/s.
IssuingOffice
Section titled “IssuingOffice”One issuing office as api.weather.gov serves it.
A record with snake_case keys, not a Record<string, string> map: the
product code is part of the answer (the same office issues different products
under different codes), and a bare map would have nowhere to put it.
Properties
Section titled “Properties”code:
string
Office identifier as served, e.g. "HGX".
name:
string
Human-readable office name, e.g. "Houston TX".
product_code
Section titled “product_code”product_code:
string
The AWIPS product code this list was requested for, e.g. "PSH".
IssuingOfficesOptions
Section titled “IssuingOfficesOptions”Extends
Section titled “Extends”FetchWithRetryOptions
Properties
Section titled “Properties”productCode?
Section titled “productCode?”
optionalproductCode:string
AWIPS product code to list offices for. Default "PSH".
LatestOptions
Section titled “LatestOptions”Properties
Section titled “Properties”source?
Section titled “source?”
readonlyoptionalsource:null|string
Live source to poll. "awc" (default, fastest) or "iem" (~10-min
delay; useful when AWC is down). Case-insensitive.
Observation
Section titled “Observation”Single observation row, matching specs/observation.json.
Notes on null vs unknown:
- Every field defaults to
nullif the upstream record omits it, fails bounds, or fails type parsing. This mirrors the Python parser (no exceptions on bad input — only on missing required keys). sourceis always the string literal"awc"for AWC-sourced rows (the row-level enum is"awc" | "iem" | "ghcnh"; the.live/.archivesuffix is a catalog source-id, not a row field).event_time_utcis ISO 8601 UTC withZsuffix.
Properties
Section titled “Properties”altimeter_inhg
Section titled “altimeter_inhg”
readonlyaltimeter_inhg:null|number
dewpoint_c
Section titled “dewpoint_c”
readonlydewpoint_c:null|number
dewpoint_f
Section titled “dewpoint_f”
readonlydewpoint_f:null|number
event_time_utc
Section titled “event_time_utc”
readonlyevent_time_utc:string
observation_type
Section titled “observation_type”
readonlyobservation_type:"METAR"|"SPECI"
peak_wind_dir
Section titled “peak_wind_dir”
readonlypeak_wind_dir:null|number
peak_wind_gust_kt
Section titled “peak_wind_gust_kt”
readonlypeak_wind_gust_kt:null|number
peak_wind_time
Section titled “peak_wind_time”
readonlypeak_wind_time:null|string
precipitation_in_1h
Section titled “precipitation_in_1h”
readonlyprecipitation_in_1h:null|number
qc_field
Section titled “qc_field”
readonlyqc_field:null|number
raw_metar
Section titled “raw_metar”
readonlyraw_metar:null|string
sea_level_pressure_hpa
Section titled “sea_level_pressure_hpa”
readonlysea_level_pressure_hpa:null|number
sky_base_1_ft
Section titled “sky_base_1_ft”
readonlysky_base_1_ft:null|number
sky_base_2_ft
Section titled “sky_base_2_ft”
readonlysky_base_2_ft:null|number
sky_base_3_ft
Section titled “sky_base_3_ft”
readonlysky_base_3_ft:null|number
sky_base_4_ft
Section titled “sky_base_4_ft”
readonlysky_base_4_ft:null|number
sky_cover_1
Section titled “sky_cover_1”
readonlysky_cover_1:null|string
sky_cover_2
Section titled “sky_cover_2”
readonlysky_cover_2:null|string
sky_cover_3
Section titled “sky_cover_3”
readonlysky_cover_3:null|string
sky_cover_4
Section titled “sky_cover_4”
readonlysky_cover_4:null|string
snow_depth_inches
Section titled “snow_depth_inches”
readonlysnow_depth_inches:null|number
source
Section titled “source”
readonlysource:"awc"|"ghcnh"|"iem"
Per-row source tag for AWC live, IEM ASOS archive, or GHCNh archive. Each
parser still emits its own literal — AWC emits "awc", IEM ASOS emits
"iem", GHCNh emits "ghcnh" — but the shared Observation contract
accepts all three so mergeObservations sees one row shape across sources.
station_code
Section titled “station_code”
readonlystation_code:string
temp_c
Section titled “temp_c”
readonlytemp_c:null|number
temp_f
Section titled “temp_f”
readonlytemp_f:null|number
visibility_miles
Section titled “visibility_miles”
readonlyvisibility_miles:null|number
weather_codes
Section titled “weather_codes”
readonlyweather_codes:null|string
wind_dir_degrees
Section titled “wind_dir_degrees”
readonlywind_dir_degrees:null|number
wind_gust_kt
Section titled “wind_gust_kt”
readonlywind_gust_kt:null|number
wind_speed_kt
Section titled “wind_speed_kt”
readonlywind_speed_kt:null|number
ObsOptions
Section titled “ObsOptions”Properties
Section titled “Properties”reportType?
Section titled “reportType?”
optionalreportType:"metar"|"speci"|"all"
Which report kinds to return — "all" (default, both hourly METAR
and off-hour SPECI), "metar" (hourly only), or "speci" (special
reports only). Filters on the per-row observation_type. Mirrors Python
observations(..., report_type=...). Note the TS IEM leg fetches
reportType: 3 (METAR) from IEM, so a "speci" filter returns only AWC
SPECI rows; IEM SPECI rows are not fetched in TypeScript.
signal?
Section titled “signal?”
optionalsignal:AbortSignal
Caller abort signal, propagated to every IEM/AWC fetch (and composed with
each attempt’s retry backoff wait). An abort mid-flight rejects promptly
with the platform AbortError — never reclassified as a transport error.
source?
Section titled “source?”
optionalsource:ObsSourceFilter
Optional source filter. null (default) means all sources merged.
strategy?
Section titled “strategy?”
optionalstrategy:ObsStrategy
Strategy mode; default "auto".
timezone?
Section titled “timezone?”
optionaltimezone:string
IANA timezone override forwarded to the
local_standard_date LST-bucketing machinery (mirrors Python observations(..., timezone=...)). Rarely needed for the canonical station registry (all
covered); used for stations whose tz is not in the registry.
ObsRow
Section titled “ObsRow”Single observation row. Field set mirrors the canonical Observation
schema (@mostlyrightmd/weather Observation interface) with the
METAR-derived fields (temp_f / dewpoint_f / wind_speed_kts / …).
Properties
Section titled “Properties”dewpoint_c?
Section titled “dewpoint_c?”
optionaldewpoint_c:null|number
dewpoint_f?
Section titled “dewpoint_f?”
optionaldewpoint_f:null|number
event_time_utc
Section titled “event_time_utc”event_time_utc:
string
knowledge_time?
Section titled “knowledge_time?”
optionalknowledge_time:string
Point-in-time key = event_time_utc + the per-source broadcast lag
(awc +5min, iem +15min, ghcnh +6h), serialized as an ISO-8601 UTC
string. Mirrors Python’s knowledge_time column (a tz-aware datetime64
there; a plain ISO string here — JS has no datetime64). Present on every
per-report row with a parseable event_time_utc.
local_standard_date?
Section titled “local_standard_date?”
optionallocal_standard_date:string
ISO YYYY-MM-DD string of the local standard day this report belongs to,
computed via localStandardDateFor (never a raw event_time_utc[:10] UTC-day
slice — a pre-midnight-UTC METAR belongs to the PRIOR LST day for
negative-offset US stations). Present on every per-report row with a
parseable event_time_utc; it is the per-report join key the composed
observation-grain dataset uses to LEFT-join daily columns onto each report.
observation_type?
Section titled “observation_type?”
optionalobservation_type:"METAR"|"SPECI"
"METAR" (hourly) | "SPECI" (off-hour special). Mirrors Python’s
observation_type column; the reportType option filters on it.
precipitation_mm_1h?
Section titled “precipitation_mm_1h?”
optionalprecipitation_mm_1h:null|number
pressure_inhg?
Section titled “pressure_inhg?”
optionalpressure_inhg:null|number
raw_metar?
Section titled “raw_metar?”
optionalraw_metar:null|string
source
Section titled “source”source:
string
station
Section titled “station”station:
string
temp_c
Section titled “temp_c”temp_c:
null|number
temp_f
Section titled “temp_f”temp_f:
null|number
wind_direction_degrees?
Section titled “wind_direction_degrees?”
optionalwind_direction_degrees:null|number
wind_speed_kts?
Section titled “wind_speed_kts?”
optionalwind_speed_kts:null|number
OpenMeteoOptions
Section titled “OpenMeteoOptions”Optional knobs for openMeteoForecasts.
Properties
Section titled “Properties”allowLeakage?
Section titled “allowLeakage?”
readonlyoptionalallowLeakage:boolean
Required true to invoke mode: "seamless".
fetchFn()?
Section titled “fetchFn()?”
readonlyoptionalfetchFn: (input,init?) =>Promise<Response>(input,init?) =>Promise<Response>
Override the fetch function (used by tests).
Parameters
Section titled “Parameters”URL | RequestInfo
RequestInit
Returns
Section titled “Returns”Promise<Response>
Parameters
Section titled “Parameters”string | URL | Request
RequestInit
Returns
Section titled “Returns”Promise<Response>
issuedAt?
Section titled “issuedAt?”
readonlyoptionalissuedAt:string
Optional ISO cycle for Single Runs API dispatch.
readonlyoptionalmode:OpenMeteoMode
Default "training".
model?
Section titled “model?”
readonlyoptionalmodel:OpenMeteoModel
Default "gfs_global".
signal?
Section titled “signal?”
readonlyoptionalsignal:AbortSignal
Caller abort signal. Propagated to the forecast fetch; an abort during an
in-flight request rejects promptly with the platform AbortError.
OpenMeteoRow
Section titled “OpenMeteoRow”One Open-Meteo forecast row (schema.forecast.station.v1).
Properties
Section titled “Properties”apparentTempC
Section titled “apparentTempC”
readonlyapparentTempC:null|number
capeJkg
Section titled “capeJkg”
readonlycapeJkg:null|number
cloudCoverPct
Section titled “cloudCoverPct”
readonlycloudCoverPct:null|number
dewPointC
Section titled “dewPointC”
readonlydewPointC:null|number
directRadiationWm2
Section titled “directRadiationWm2”
readonlydirectRadiationWm2:null|number
forecastHour
Section titled “forecastHour”
readonlyforecastHour:null|number
(validAt - issuedAt) in hours. null when issuedAt is null.
freezingLevelM
Section titled “freezingLevelM”
readonlyfreezingLevelM:null|number
issuedAt
Section titled “issuedAt”
readonlyissuedAt:null|string
Model run datetime — UTC ISO string. May be null for
source="open_meteo.seamless" rows (cycle unrecoverable by design).
readonlymodel:string
Open-Meteo model key (lowercase, e.g. "gfs_global").
precipitationMm
Section titled “precipitationMm”
readonlyprecipitationMm:null|number
precipProbability
Section titled “precipProbability”
readonlyprecipProbability:null|number
pressureMslHpa
Section titled “pressureMslHpa”
readonlypressureMslHpa:null|number
retrievedAt
Section titled “retrievedAt”
readonlyretrievedAt:string
shortwaveRadiationWm2
Section titled “shortwaveRadiationWm2”
readonlyshortwaveRadiationWm2:null|number
snowDepthM
Section titled “snowDepthM”
readonlysnowDepthM:null|number
source
Section titled “source”
readonlysource:OpenMeteoSource
station
Section titled “station”
readonlystation:string
surfacePressureHpa
Section titled “surfacePressureHpa”
readonlysurfacePressureHpa:null|number
readonlytempC:null|number
validAt
Section titled “validAt”
readonlyvalidAt:string
visibilityM
Section titled “visibilityM”
readonlyvisibilityM:null|number
weatherCode
Section titled “weatherCode”
readonlyweatherCode:null|number
windDirDeg
Section titled “windDirDeg”
readonlywindDirDeg:null|number
windGustsMs
Section titled “windGustsMs”
readonlywindGustsMs:null|number
windSpeedMs
Section titled “windSpeedMs”
readonlywindSpeedMs:null|number
PostStormReportsOptions
Section titled “PostStormReportsOptions”Options for postStormReports.
Same shape as TextProductsOptions minus productCode: a post-storm
report is PSH by definition, and offering the code would let a caller ask
this verb for something that is not a post-storm report.
Extends
Section titled “Extends”Omit<TextProductsOptions,"productCode">
Properties
Section titled “Properties”fromTime?
Section titled “fromTime?”
optionalfromTime:string
Window start, ISO-8601 with a Z offset.
Inherited from
Section titled “Inherited from”Omit.fromTime
limit?
Section titled “limit?”
optionallimit:number
Page size for the live route.
Inherited from
Section titled “Inherited from”Omit.limit
office?
Section titled “office?”
optionaloffice:string
Issuing office (AFOS cccc), e.g. "KNHC". Archive route only.
Inherited from
Section titled “Inherited from”Omit.office
productId?
Section titled “productId?”
optionalproductId:string
Fetch one product by id. An identity call: a product id that yields no
bulletin text throws NoHazardDataError naming the id, never an empty
result. Ignores fromTime / toTime.
Inherited from
Section titled “Inherited from”Omit.productId
source?
Section titled “source?”
optionalsource:TextProductsSource
Which route answers. Unset auto-routes on the window age.
Inherited from
Section titled “Inherited from”Omit.source
toTime?
Section titled “toTime?”
optionaltoTime:string
Window end, ISO-8601 with a Z offset.
Inherited from
Section titled “Inherited from”Omit.toTime
vintages?
Section titled “vintages?”
optionalvintages:Vintages
Row selector. Default "all". See Vintages.
Inherited from
Section titled “Inherited from”Omit.vintages
StageAndFlowOptions
Section titled “StageAndFlowOptions”Options for stageAndFlow().
Extends
Section titled “Extends”FetchWithRetryOptions
Properties
Section titled “Properties”series?
Section titled “series?”
optionalseries:WaterSeries
Read one series instead of both. Unset reads the combined document and
returns BOTH products in one result, discriminated by the series column.
The option is called series and not product because product_code
already names an NWS text bulletin in this schema family, and one word must
not name two things. A value the route does not serve throws before any
request.
StreamOptions
Section titled “StreamOptions”Properties
Section titled “Properties”pollSeconds?
Section titled “pollSeconds?”
readonlyoptionalpollSeconds:null|number
Override the polite-floor cadence. Must be >= the per-source floor
(AWC=30, IEM=60). When omitted, uses the floor for the active source.
signal?
Section titled “signal?”
readonlyoptionalsignal:AbortSignal
Optional AbortSignal for clean cancellation. When fired, the current
polite-floor sleep is interrupted and the generator returns. The current
in-flight fetch (if any) is allowed to complete — AbortSignal is not
threaded into the underlying fetchers, which wrap the platform fetch
synchronously.
source?
Section titled “source?”
readonlyoptionalsource:null|string
Live source to poll. "awc" (default) or "iem". Case-insensitive.
TextProductsOptions
Section titled “TextProductsOptions”Extends
Section titled “Extends”FetchWithRetryOptions
Properties
Section titled “Properties”fromTime?
Section titled “fromTime?”
optionalfromTime:string
Window start, ISO-8601 with a Z offset.
limit?
Section titled “limit?”
optionallimit:number
Page size for the live route.
office?
Section titled “office?”
optionaloffice:string
Issuing office (AFOS cccc), e.g. "KNHC". Archive route only.
productCode?
Section titled “productCode?”
optionalproductCode:string
AWIPS product code. Default "TCP" (the public advisory).
productId?
Section titled “productId?”
optionalproductId:string
Fetch one product by id. An identity call: a product id that yields no
bulletin text throws NoHazardDataError naming the id, never an empty
result. Ignores fromTime / toTime.
source?
Section titled “source?”
optionalsource:TextProductsSource
Which route answers. Unset auto-routes on the window age.
toTime?
Section titled “toTime?”
optionaltoTime:string
Window end, ISO-8601 with a Z offset.
vintages?
Section titled “vintages?”
optionalvintages:Vintages
Row selector. Default "all". See Vintages.
TropicalCyclonesOptions
Section titled “TropicalCyclonesOptions”Extends
Section titled “Extends”FetchWithRetryOptions
Properties
Section titled “Properties”source?
Section titled “source?”
optionalsource:"nhc"
Which route answers. Default "nhc".
vintages?
Section titled “vintages?”
optionalvintages:Vintages
Row selector. Default "all". See Vintages.
WaterObservationsOptions
Section titled “WaterObservationsOptions”Options for waterObservations().
Extends
Section titled “Extends”FetchWithRetryOptions
Properties
Section titled “Properties”approvalStatus?
Section titled “approvalStatus?”
optionalapprovalStatus:WaterApprovalStatus
Keep only rows in this state.
An ordinary FILTER over a column, never a vintage selector: “provisional”
is a property of the datum, not of when this install learned it. The
knowledge time is last_modified_at_utc, which the upstream supplies and
every row carries. A value USGS does not publish throws before any request.
parameterCode?
Section titled “parameterCode?”
optionalparameterCode:"00065"|"00060"
USGS parameter code: "00065" (gage height, ft — the default) or
"00060" (discharge, ft³/s).
A closed set, not a free string: anything else returns rows whose units no
column on this schema names. Checked at compile time by this union and at
runtime in fetchContinuous, matching _check_parameter_code.
WildfiresOptions
Section titled “WildfiresOptions”Options for wildfires().
Extends
Section titled “Extends”FetchWithRetryOptions
Properties
Section titled “Properties”activeOnly?
Section titled “activeOnly?”
optionalactiveOnly:boolean
Ask the California route for the incidents burning right now rather than the whole season. Refused with the interagency source.
fromDate?
Section titled “fromDate?”
optionalfromDate:string
Earliest discovery day to keep. Refused with source: "calfire", and
refused against scope: "current" when it predates the fall-off horizon.
incidentType?
Section titled “incidentType?”
optionalincidentType:null|string
The incident category to keep.
Interpreted PER SOURCE, because the two upstreams genuinely use different
vocabularies and this SDK does not invent a third to paper over it: on the
interagency leg it is a category ("WF", "RX", "CX"), and on the state
leg it is a type ("Wildfire", "Fire", "Flood", "Hazmat"). The
default is "WF", and the state leg reads that default as its own
"Wildfire". null disables the filter and returns every category the leg
serves.
includeComplexChildren?
Section titled “includeComplexChildren?”
optionalincludeComplexChildren:boolean
Keep the child incidents that roll up into a complex. Defaults to false,
because a complex parent and its children both report acreage and summing
both double-counts. Refused with source: "calfire".
minAcres?
Section titled “minAcres?”
optionalminAcres:number
Keep only incidents at or above this size in acres. Refused with source: "calfire".
scope?
Section titled “scope?”
optionalscope:WfigsScope
Which interagency window. Defaults to "current". Refused with source: "calfire".
source?
Section titled “source?”
optionalsource:WildfireSource
Which provider answers. Unset means the interagency feed.
state?
Section titled “state?”
optionalstate:string
A two-letter state code, matched against the upstream’s country-prefixed
token. Refused with source: "calfire", whose every row is California.
toDate?
Section titled “toDate?”
optionaltoDate:string
Latest discovery day to keep, inclusive. Refused with source: "calfire".
optionalyear:number
Which California season. Refused with the interagency source, which selects
a window through scope instead.
Type Aliases
Section titled “Type Aliases”AlertsSource
Section titled “AlertsSource”AlertsSource:
"nws"|"iem"
Which route answers.
"nws" (the default) reads the live CAP feed at api.weather.gov/alerts,
which retains exactly 7 days; a fromTime older than that throws
HazardRetentionError instead of returning an empty result.
"iem" reads the Iowa State VTEC archive, which covers 2005 onward and has
no retention cliff. One verb, one source axis — there is no separate
alertHistory verb to remember.
CalendarDay
Section titled “CalendarDay”CalendarDay:
string
A calendar DAY, spelled YYYY-MM-DD.
Deliberately not a Date: a Date is an instant, and reading a calendar day
off one needs a timezone this SDK would have to guess. Python’s twin takes a
datetime.date, which TypeScript has no equivalent of, so the string spelling
is the honest one here. Both SDKs convert the day to an absolute
epoch-millisecond boundary before it reaches a query.
DailyExtremesMergeMode
Section titled “DailyExtremesMergeMode”DailyExtremesMergeMode:
"live_v1"|"awc_only"|"iem_only"
Merge mode controlling which sources contribute observations.
live_v1(default) — IEM ASOS for historical depth + AWC for the recent 168h window. Matches Pythonmerge="live_v1".awc_only— AWC live METAR only. Window must be inside the 168h AWC retention or callers see a sparse return.iem_only— IEM ASOS archive only. No live fallback.
FirmsRegion
Section titled “FirmsRegion”FirmsRegion:
"usa"|"alaska"|"canada"|"global"
The four regions the keyless bulk tier publishes.
FirmsSensor
Section titled “FirmsSensor”FirmsSensor:
"viirs_snpp"|"viirs_noaa20"|"viirs_noaa21"|"modis"
The four platforms both routes serve.
GaugeBbox
Section titled “GaugeBbox”GaugeBbox: readonly [
number,number,number,number]
A bounding box as the NWPS inventory route states it:
[xmin, ymin, xmax, ymax] — west, south, east, north — in the units of
GaugesOptions.srid.
HotspotBbox
Section titled “HotspotBbox”HotspotBbox: readonly [
number,number,number,number]
A bounding box in degrees, ordered west, south, east, north.
HotspotSource
Section titled “HotspotSource”HotspotSource:
"firms.bulk"|"firms.area"
Which detection route answers.
Unset and "firms.bulk" both take the KEYLESS bulk tier, which is the
default precisely so an install that has never registered for anything gets
working detections — and so a build that reaches only this route never reads
a key. "firms.area" takes the bounding-box route, which needs a key of your
own in MOSTLYRIGHT_FIRMS_MAP_KEY.
IemMosModel
Section titled “IemMosModel”IemMosModel:
"nbe"|"gfs"|"lav"|"met"|"ecm"
IEM MOS model enum.
IemMosSource
Section titled “IemMosSource”IemMosSource:
"iem.archive"|"iem.live"
Canonical source enum.
LiveObservation
Section titled “LiveObservation”LiveObservation:
Omit<Observation,"source"> &object
Observation row emitted by mostlyright.live.stream and live.latest.
Same shape as the canonical Observation row, but with source narrowed
to the live-channel identity tags. The archive-channel "awc" / "iem"
/ "ghcnh" source values are not valid here, which is why live rows carry
their own type.
Type declaration
Section titled “Type declaration”source
Section titled “source”
readonlysource:LiveSourceTag
LiveSource
Section titled “LiveSource”LiveSource: typeof
SUPPORTED_SOURCES[number]
Validated source enum derived from SUPPORTED_SOURCES.
LiveSourceTag
Section titled “LiveSourceTag”LiveSourceTag: typeof
SOURCE_IDENTITY_TAGS[LiveSource]
NwpModel
Section titled “NwpModel”NwpModel:
"hrrr"|"gfs"|"nbm"|"hrrrak"|"gefs"|"gdas"|"rap"|"rrfs"|"rtma"|"urma"|"cfs"|"ecmwf_ifs_hres"|"ecmwf_ifs_ens"|"ecmwf_aifs_single"|"ecmwf_aifs_ens"|"hrdps"|"rdps"|"gdps"|"geps"|"reps"|"hafs"|"nam"|"href"|"hiresw"
Supported NWP model identifiers.
ObsFrameSource
Section titled “ObsFrameSource”ObsFrameSource:
"merged.live_v1"|"awc"|"iem"|"ghcnh"
Frame-level source identity — serialized as provenance.source on the
@mostlyrightmd/core!DataResult returned by observations().
Value mirrors Python df.attrs["source"]:
- unpinned (
sourceomitted / null) →"merged.live_v1"(the merged-frame tag, which a single-source/pinned schema rejects). - pinned (
sourceset) → the bare pinned source ("awc"/"iem").
ObsSourceFilter
Section titled “ObsSourceFilter”ObsSourceFilter:
"awc"|"iem"|"ghcnh"|null
Source filter — matches Python weather.observations(source=...) and its
_VALID_SOURCES frozenset {"awc", "iem", "ghcnh"}. null (default) means
all sources merged.
ghcnh validates as accepted but is not available through this TypeScript
path; selecting it raises
DataAvailabilityError(reason="model_unavailable") rather than returning
[].
ObsStrategy
Section titled “ObsStrategy”ObsStrategy:
"auto"|"exact_window"|"warm_cache"|"hosted"
Observation fetch strategy.
OpenMeteoMode
Section titled “OpenMeteoMode”OpenMeteoMode:
"training"|"live"|"seamless"
Open-Meteo dispatch mode for openMeteoForecasts.
OpenMeteoModel
Section titled “OpenMeteoModel”OpenMeteoModel:
"gfs_seamless"|"gfs_global"|"gfs_graphcast025"|"aigfs025"|"hgefs025"|"ncep_hrrr_conus"|"ncep_nbm_conus"|"ncep_nam_conus"|"ecmwf_ifs025"|"ecmwf_ifs_hres"|"ecmwf_aifs025_single"|"dwd_icon_seamless"|"dwd_icon_global"|"dwd_icon_eu"|"dwd_icon_d2"|"dwd_icon_d2_15min"|"meteofrance_seamless"|"meteofrance_arpege_world025"|"meteofrance_arpege_europe"|"meteofrance_arome_france0025"|"meteofrance_arome_france_hd"|"meteofrance_arome_france_hd_15min"|"jma_seamless"|"jma_gsm"|"jma_msm"|"kma_seamless"|"kma_gdps"|"kma_ldps"|"cma_grapes_global"|"bom_access_global"|"ukmo_global_deterministic_10km"|"ukmo_uk_deterministic_2km"|"metno_nordic_pp"|"cmc_gem_gdps"|"cmc_gem_rdps"|"cmc_gem_hrdps"
The 36 Open-Meteo forecast models in scope.
OpenMeteoSource
Section titled “OpenMeteoSource”OpenMeteoSource:
"open_meteo.previous_runs"|"open_meteo.single_run"|"open_meteo.live"|"open_meteo.seamless"
Open-Meteo source-identity enum (per-endpoint discrimination).
RatingCurveOptions
Section titled “RatingCurveOptions”RatingCurveOptions:
FetchWithRetryOptions
Options for ratingCurve().
Transport controls only, on purpose. The measured curve is 303 points and
16,169 bytes and always arrives whole and ascending by stage_ft, so slicing
options over a small ordered table buy a caller nothing that an array slice
does not already give them. The Python twin refuses the same ones.
ReportType
Section titled “ReportType”ReportType:
"final"|"ncei_final"|"correction"|"preliminary"|"estimated"
TextProductsSource
Section titled “TextProductsSource”TextProductsSource:
"nws"|"iem"
Which route answers.
"nws" reads api.weather.gov/products, which retains 7 days. "iem" reads
the Iowa State AFOS archive, the only route that carries intermediate
advisories (the ones with a letter suffix) and PSH amendments.
Left unset, the verb chooses: a window inside the 7-day retention goes to the
live route, an older one auto-routes to the archive. Unlike alerts, an old
window here is a route change, not a rejection — the archive serves the same
product, so there is nothing for the caller to decide.
TropicalCyclonesSource
Section titled “TropicalCyclonesSource”TropicalCyclonesSource:
"nhc"
Which route answers. One value today: NHC’s CurrentStorms.json is the only
feed that serves active tropical cyclones, and there is no archive of that
document. The option exists so a second leg can be added without changing the
call shape.
Vintages
Section titled “Vintages”Vintages:
"all"|"latest"
Row selector for the hazard verbs.
"all" (the default) keeps every row the route returned, including repeated
captures of the same identity. "latest" keeps one row per identity — the
one with the greatest captured_at, ties broken by upstream order.
Unlike Python, the TypeScript SDK keeps no local capture ledger: nothing is persisted, so the selector applies to rows the caller has already fetched in this call rather than to a stored vintage history.
@mostlyrightmd/economy’s series.ts exports a different type under the
same name, accepting "settlement" | "all". The two are unrelated; check
which package a Vintages value is destined for before passing a literal.
What “one row per identity” means differs per verb, and each one matches the
Python partition key in hazards/_cache.py’s _HAZARD_PARTITION_KEYS so the
same keyword performs the same reduction in both SDKs:
| verb | identity |
|---|---|
alerts | (alert_id, ugc_zone) |
textProducts / postStormReports | (product_id), amendment suffix included |
tropicalCyclones | (storm_id, last_update_at_utc) — one row per storm state, not per storm |
bestTrack | (storm_id, valid_at_utc) |
WaterApprovalStatus
Section titled “WaterApprovalStatus”WaterApprovalStatus:
"Provisional"|"Approved"
The two states USGS publishes a continuous value in.
WaterSeries
Section titled “WaterSeries”WaterSeries:
"observed"|"forecast"
One of the two series the stage-and-flow route serves.
WfigsScope
Section titled “WfigsScope”WfigsScope:
"current"|"season"|"history"
Which interagency window answers.
"current" serves the fires that are neither contained, controlled, nor out
AND have been updated recently — it drops records under published fall-off
rules, so it cannot answer a past window. "season" serves the whole current
calendar year with no fall-off. "history" serves every year the interagency
reporting system has recorded.
WildfireSource
Section titled “WildfireSource”WildfireSource:
"wfigs"|"calfire"
Which provider answers.
The provenance axis, mirroring the Python source= set. Unset and "wfigs"
both serve the national interagency feed through scope; "calfire" serves
the California state feed through year / activeOnly. There is no
separate California verb, and the name it would have had is spelled nowhere in
this package so a grep for it stays a gate: a second name for the same row
contract differing only in who produced it is exactly what this axis exists to
express.
Variables
Section titled “Variables”FIRMS_ATTRIBUTION
Section titled “FIRMS_ATTRIBUTION”
constFIRMS_ATTRIBUTION:string
The acknowledgment NASA asks for, verbatim.
Byte-identical to Python’s FIRMS_ATTRIBUTION. Written into the
attribution COLUMN of every hotspot row, and carried on the result metadata
too — including on an empty result, where there is no row to carry it.
HIGH_TEMP_MAX_F
Section titled “HIGH_TEMP_MAX_F”
constHIGH_TEMP_MAX_F:150=150
HIGH_TEMP_MIN_F
Section titled “HIGH_TEMP_MIN_F”
constHIGH_TEMP_MIN_F:-60=-60
Climate temp bounds from specs/climate.json. Inclusive.
LOW_TEMP_MAX_F
Section titled “LOW_TEMP_MAX_F”
constLOW_TEMP_MAX_F:130=130
LOW_TEMP_MIN_F
Section titled “LOW_TEMP_MIN_F”
constLOW_TEMP_MIN_F:-80=-80
OPEN_METEO_MODELS
Section titled “OPEN_METEO_MODELS”
constOPEN_METEO_MODELS:ReadonlySet<OpenMeteoModel>
The canonical 36-model set. The test suite compares this by set equality, so an added or dropped model fails rather than passing silently.
POLITE_FLOORS_S
Section titled “POLITE_FLOORS_S”
constPOLITE_FLOORS_S:Readonly<Record<LiveSource,number>>
Minimum allowed poll cadence per source, in seconds.
- AWC: 30s — aviationweather.gov has no documented rate limit but 30s is the empirically-validated floor that won’t trip anti-abuse heuristics.
- IEM: 60s — mesonet.agron.iastate.edu is a university server; IEM docs explicitly ask for reasonable headroom above 1 req/s.
SOURCE_IDENTITY_TAGS
Section titled “SOURCE_IDENTITY_TAGS”
constSOURCE_IDENTITY_TAGS:object
Canonical per-source source field tag emitted on every observation row.
"awc.live" / "iem.live" are the live-channel identity tags — distinct
from the archive-channel "awc" / "iem" written by the historical
fetchers. Cross-SDK parity: these match Python SOURCE_IDENTITY_TAGS.
Type declaration
Section titled “Type declaration”
readonlyawc:"awc.live"="awc.live"
readonlyiem:"iem.live"="iem.live"
SUPPORTED_SOURCES
Section titled “SUPPORTED_SOURCES”
constSUPPORTED_SOURCES: readonly ["awc","iem"]
Canonical ordered tuple of supported sources. Order matters — keep AWC first.
version
Section titled “version”
constversion:"4.1.0"="4.1.0"
Public package version; matches package.json.
Functions
Section titled “Functions”alerts()
Section titled “alerts()”alerts(
opts):Promise<DataResult<HazardAlertV1>>
Fetch CAP hazard alerts at the (issuance x UGC zone) grain.
Mirrors Python mostlyright.weather.hazards.alerts(...). Returns
DataResult<HazardAlertV1>: snake_case rows plus the provenance envelope
whose source is the tag of the leg that answered ("nws.alerts.live" or
"iem.vtec.archive"). Every row carries the same tag in its own source
column.
One alert covering two zones produces two rows sharing alert_id. An alert
that was updated appears once per issuance, with references recording which
issuance each one supersedes — do not collapse on (zone, event), that
discards the supersession history this adapter exists to capture.
Parameters
Section titled “Parameters”AlertsOptions = {}
Returns
Section titled “Returns”Promise<DataResult<HazardAlertV1>>
Throws
Section titled “Throws”HazardRetentionError when fromTime predates the live route’s 7-day
retention and source is not "iem". Thrown before any request.
Throws
Section titled “Throws”ContractError when source: "iem" is asked for without a window (the
archive route has no “everything” mode), or is combined with event (the
archive serves VTEC codes, not NWS event names).
bestTrack()
Section titled “bestTrack()”bestTrack(
stormId,opts):Promise<DataResult<HazardBestTrackV1>>
Fetch the HURDAT2 best-track fixes for one storm.
Parameters
Section titled “Parameters”stormId
Section titled “stormId”string
NHC storm id, e.g. "AL142024". Matched case-insensitively.
BestTrackOptions = {}
Returns
Section titled “Returns”Promise<DataResult<HazardBestTrackV1>>
Remarks
Section titled “Remarks”Node-only. www.nhc.noaa.gov sends no Access-Control-Allow-Origin header
(measured 1 August 2026); calling this from a browser page will fail CORS,
so this verb refuses there with a typed ContractError. A Node process, a
Cloudflare Worker, or an extension service worker with www.nhc.noaa.gov in
host_permissions can call it.
Mirrors Python mostlyright.weather.hazards.best_track(...). Returns
DataResult<HazardBestTrackV1> stamped "nhc.hurdat2", with
provenance.data_version carrying the exact file name the rows came from —
the vintage identity, since HURDAT2 has no stable “latest” alias.
Each row keeps both instants: hurdat2_revision is when the values became
knowable, valid_at_utc is the synoptic fix. For a re-analysed storm they
are years apart, which is the whole point of keeping both. landfall_flag
carries HURDAT2’s L record identifier — the settlement-relevant flag for
“hurricane hits X” contracts.
Throws
Section titled “Throws”NoHazardDataError when the selected revision carries no such storm.
bestTrackRevisions()
Section titled “bestTrackRevisions()”bestTrackRevisions(
opts):Promise<readonlyBestTrackRevision[]>
List every HURDAT2 reanalysis file the NHC directory serves.
Parameters
Section titled “Parameters”BestTrackRevisionsOptions = {}
Returns
Section titled “Returns”Promise<readonly BestTrackRevision[]>
Remarks
Section titled “Remarks”Node-only. www.nhc.noaa.gov sends no Access-Control-Allow-Origin header
(measured 1 August 2026); calling this from a browser page will fail CORS,
so this verb refuses there with a typed ContractError. A Node process, a
Cloudflare Worker, or an extension service worker with www.nhc.noaa.gov in
host_permissions can call it.
This verb enumerates files rather than rows, so it resolves to
readonly BestTrackRevision[] — the one declared non-DataResult return in
the hazard family. There is no row grain here and no schema id to stamp.
Ordered ascending by revision, never by file name: the two orders disagree,
because the date encoding in the name is six digits in some years and eight
in others.
dailyExtremes()
Section titled “dailyExtremes()”dailyExtremes(
station,fromDate,toDate,opts):Promise<DataResult<DailyExtremeRow>>
Compute per-day tmin/tmax/tmean/precip for a station’s window.
Matches Python mostlyright.international.daily_extremes signature.
Day-bucketing uses the station’s IANA local timezone from the STATIONS
registry; US ASOS stations get integer-°F precision, other stations get
0.1-precision values.
Parameters
Section titled “Parameters”station
Section titled “station”string
4-letter ICAO (e.g. “KNYC”, “EGLL”) or 3-letter NWS
registry code (e.g. “NYC”); Python daily_extremes()
accepts both. Output rows carry the ICAO whichever form
was passed in.
fromDate
Section titled “fromDate”string
ISO date YYYY-MM-DD (inclusive, station-local)
toDate
Section titled “toDate”string
ISO date YYYY-MM-DD (inclusive, station-local)
DailyExtremesOptions = {}
optional merge mode (default "live_v1")
Returns
Section titled “Returns”Promise<DataResult<DailyExtremeRow>>
array of DailyExtremeRow, one per station-local day
Throws
Section titled “Throws”Error if station is not in the STATIONS registry
forecastNwp()
Section titled “forecastNwp()”forecastNwp(
station,model,_opts):Promise<never>
Fetch a gridded NWP forecast.
Parameters
Section titled “Parameters”station
Section titled “station”string
ForecastNwpOptions = {}
Returns
Section titled “Returns”Promise<never>
Remarks
Section titled “Remarks”Not available in TypeScript. This function throws on every call. Use the Python SDK for gridded NWP.
GRIB2 decoding requires native libraries (eccodes C library or cfgrib Python wrapper). No production-ready browser-side decoder is available, and a WASM port’s compile time and bundle size are impractical.
Workaround paths:
- 7 major US stations (KNYC, KLAX, KORD, KMIA, KDEN, KSEA, KATL) → iemMosForecasts ships MOS-based forecasts that solve most use cases. The error hint includes this pointer automatically.
- Everything else → use the Python SDK
(
pip install mostlyrightmd-weather).
Throws
Section titled “Throws”NwpNotAvailableError on every call. The error
is a subclass of DataAvailabilityError, so existing
catch (e instanceof DataAvailabilityError) paths continue to catch
it. The thrown instance carries typed .station and .model
properties for log/error attribution.
docs/nwp-forecasts.md for the supported-model list and current alternatives.
gauges()
Section titled “gauges()”gauges(
opts):Promise<DataResult<HazardGaugeV1>>
Return NWPS river gauges — a bounding box of them, or one by identifier.
Parameters
Section titled “Parameters”GaugesOptions = {}
Returns
Section titled “Returns”Promise<DataResult<HazardGaugeV1>>
Remarks
Section titled “Remarks”One verb, two scopes, one identifier word. bbox enumerates the gauge
INVENTORY inside a box, tiling the request because the route serves no paging
and its unfiltered answer was measured at 13 MB and a gateway timeout.
gaugeId returns the ONE-row DETAIL record, which is the only place the
identifier crosswalk, the timezone, and the flood-category thresholds are
served. record_scope says which shape a row is.
Runs in a browser and in Node. Mirrors Python
mostlyright.weather.hazards.gauges(...) and returns
DataResult<HazardGaugeV1> stamped "nwps.gauge.live".
On an inventory row usgs_site_id, reach_id, timezone, and the eight
threshold columns are null because the LIST route omits them, not because the
gauge lacks them — read record_scope to tell the two apart. Flood thresholds
are mostly absent upstream: in a 60-gauge sample 10% carried all four stage
AND all four flow thresholds and 47% carried no stage threshold at all, which
is what thresholds_defined makes visible as a column.
Throws
Section titled “Throws”ContractError when both selectors are given or neither; when the box is inverted, zero-width, or off the globe; or when the identifier is not one the routes address.
Throws
Section titled “Throws”NotFoundError when gaugeId addresses no gauge. An identity failure
is never converted into an empty result.
Example
Section titled “Example”const basin = await gauges({ bbox: [-84, 33, -83, 34] });basin.rows[0].observed_flood_category;
const detail = await gauges({ gaugeId: "ABBG1" });detail.rows[0].action_stage_ft;hotspots()
Section titled “hotspots()”hotspots(
opts):Promise<DataResult<HazardHotspotV1>>
Return satellite thermal-anomaly detections.
Parameters
Section titled “Parameters”HotspotsOptions = {}
Returns
Section titled “Returns”Promise<DataResult<HazardHotspotV1>>
Remarks
Section titled “Remarks”NODE-ONLY, both routes: firms.modaps.eosdis.nasa.gov sends no
Access-Control-Allow-Origin header on either data route (measured
1 August 2026), so a browser page is refused at call time with a typed
ContractError rather than an opaque CORS failure. And because the key is a
URL PATH SEGMENT, a browser call on the keyed route would expose it to anyone
who can read the request — which is why the KEYLESS bulk tier is the default
and why hotspots() with no bounding box reads no MOSTLYRIGHT_FIRMS_MAP_KEY.
See docs/browser-integration.md.
With no arguments this reads the most recent published look-back file for the
default platform over the contiguous United States and Hawaii, keyless, and
returns DataResult<HazardHotspotV1> tagged "firms.bulk.live".
ATTRIBUTION. NASA asks for an acknowledgment, and it is written into the
attribution COLUMN of every row rather than into result metadata alone —
a column survives the reshaping a caller does, and an acknowledgment that
disappears on the first join is not an acknowledgment. On an empty result
there is no row to carry it, so the exported FIRMS_ATTRIBUTION constant is
the reachable copy. Python additionally stamps it on the frame’s attribute
bag, which the DataResult envelope has no equivalent of: that envelope’s key
set is pinned across every verb in this SDK.
KEYLESS names the FIRMS credential. hotspots() needs no NASA registration
and reads no MOSTLYRIGHT_FIRMS_MAP_KEY, but its address resolves through the
manifest catalog like every other source here, so MOSTLYRIGHT_API_KEY is
read and a caller with no key at all gets ApiKeyRequiredError on BOTH
routes.
persist is Python-only; see ./hotspots.types.ts.
Throws
Section titled “Throws”ContractError when source, sensor, or region is outside its
table; when bbox is passed without source: "firms.area" (the message names
both that source and MOSTLYRIGHT_FIRMS_MAP_KEY); when region is passed
with it; when the window is inverted or wider than the route can answer; or
when the keyed route is called with no key configured. It never falls back to
the keyless tier.
Throws
Section titled “Throws”SourceUnavailableError when a route answers a non-2xx. The message carries a redacted address.
Throws
Section titled “Throws”ApiKeyRequiredError when no API key is configured for catalog
resolution. This is the SDK’s own MOSTLYRIGHT_API_KEY, not the FIRMS one,
and it applies to both routes.
Example
Section titled “Example”const recent = await hotspots();recent.rows.map((row) => [row.latitude, row.longitude, row.acquired_at_utc]);
const box = await hotspots({ source: "firms.area", bbox: [-124.5, 32, -114, 42],});iemMosForecasts()
Section titled “iemMosForecasts()”iemMosForecasts(
station,fromDate,toDate,opts):Promise<DataResult<IemMosRow>>
Fetch IEM MOS forecasts for station in [fromDate, toDate].
Mirrors Python fetch_iem_mos(...). Iterates the model’s runtime-hour
grid (NBE moved from {01,07,13,19}Z to {00,06,12,18}Z on 2026-05-05;
other models use {00,06,12,18}Z), GETs the JSON endpoint, and projects
rows to IemMosRow.
404 responses are silently skipped (many runtimes have no MOS data).
Empty input range returns [].
Parameters
Section titled “Parameters”station
Section titled “station”string
fromDate
Section titled “fromDate”string
toDate
Section titled “toDate”string
IemMosOptions = {}
Returns
Section titled “Returns”Promise<DataResult<IemMosRow>>
Throws
Section titled “Throws”Error if model is not in SUPPORTED_MODELS.
isLiveSource()
Section titled “isLiveSource()”isLiveSource(
s): s is “awc” | “iem”
Type guard: narrow a string to LiveSource.
Parameters
Section titled “Parameters”string
Returns
Section titled “Returns”s is “awc” | “iem”
issuingOffices()
Section titled “issuingOffices()”issuingOffices(
opts):Promise<readonlyIssuingOffice[]>
Fetch the issuing offices that publish one product code.
Mirrors Python mostlyright.weather.hazards.issuing_offices(...). Reads the
served api.weather.gov/products/types/{code}/locations route, so the list
stays current — no office code is hardcoded anywhere in this module.
Returns readonly IssuingOffice[] sorted by code: a record list rather
than a Record<string, string> map, because the product code is part of the
answer and a bare map has nowhere to put it.
Parameters
Section titled “Parameters”Returns
Section titled “Returns”Promise<readonly IssuingOffice[]>
latest()
Section titled “latest()”latest(
station,opts):Promise<LiveObservation>
Return the most-recent observation row for station from a single source.
Same fetch path as stream, but returns once instead of looping. Use this for cron-style polling where you want one fresh observation per invocation.
Parameters
Section titled “Parameters”station
Section titled “station”string
ICAO ("KNYC") or 3-letter US ID ("NYC"). Case-insensitive.
LatestOptions = {}
Optional { source }.
Returns
Section titled “Returns”Promise<LiveObservation>
Throws
Section titled “Throws”Error when opts.source is unknown.
Throws
Section titled “Throws”NoLiveDataError when the upstream returned no observations
for the station — payload carries the resolved station and live
source tag for branching.
observations()
Section titled “observations()”observations(
rawStation,fromDate,toDate,opts):Promise<DataResult<ObsRow>>
Fetch the merged per-report observations for a station’s window.
Mirrors Python mostlyright.weather.observations(station, from_date, to_date, source=None) — per-report rows only. The strategy option selects one of
the concrete fetch paths described at the top of this file.
The returned DataResult carries provenance.source ("merged.live_v1"
when unpinned, the bare source when pinned), mirroring Python’s
df.attrs["source"]. Every row carries a local_standard_date.
Parameters
Section titled “Parameters”rawStation
Section titled “rawStation”string
ICAO code (e.g. “KNYC”) OR 3-letter NWS code (e.g. “NYC”). Resolved through the station registry: IEM ASOS is fetched by the NWS code, AWC by the ICAO — so observations(“KNYC”) == observations(“NYC”).
fromDate
Section titled “fromDate”string
ISO date YYYY-MM-DD (inclusive)
toDate
Section titled “toDate”string
ISO date YYYY-MM-DD (inclusive)
ObsOptions = {}
optional source filter + strategy mode
Returns
Section titled “Returns”Promise<DataResult<ObsRow>>
DataResult<ObsRow>: the per-report rows plus provenance
Throws
Section titled “Throws”ValidationError when station is malformed or not in the registry (before any fetch — same typed error dailySummaries() throws)
Throws
Section titled “Throws”DataAvailabilityError when strategy=‘hosted’ (the hosted ingest API is not available yet)
Throws
Section titled “Throws”TypeError when strategy is not in the accepted enum
openMeteoForecasts()
Section titled “openMeteoForecasts()”openMeteoForecasts(
station,fromDate,toDate,opts):Promise<DataResult<OpenMeteoRow>>
Fetch Open-Meteo forecasts for station in [fromDate, toDate].
Mirrors Python fetch_open_meteo. Default mode: "training" hits the
Previous Runs API; with issuedAt: "..."
dispatches to Single Runs API. mode: "live" hits Live Forecast API
with cycle-math fallback issuedAt. mode: "seamless" requires
allowLeakage: true, and is refused for training data without it.
Parameters
Section titled “Parameters”station
Section titled “station”string
fromDate
Section titled “fromDate”string
toDate
Section titled “toDate”string
OpenMeteoOptions = {}
Returns
Section titled “Returns”Promise<DataResult<OpenMeteoRow>>
postStormReports()
Section titled “postStormReports()”postStormReports(
opts):Promise<DataResult<HazardTextProductV1>>
Fetch post-storm reports (PSH) — the per-city damage bulletins.
Mirrors Python mostlyright.weather.hazards.post_storm_reports(...). Same
rows, same routes, and the same auto-route on window age as
textProducts; the product code is fixed to PSH, because a
post-storm report is that code by definition.
Amendments are preserved. product_id keeps its -AAA / -BBB correction
suffix, so two amendments of the same report appear as two rows and
vintages: "latest" does not collapse them — they are different products,
and treating the first as final loses the correction.
Parameters
Section titled “Parameters”Returns
Section titled “Returns”Promise<DataResult<HazardTextProductV1>>
ratingCurve()
Section titled “ratingCurve()”ratingCurve(
gaugeId,opts):Promise<DataResult<HazardRatingCurveV1>>
Return a gauge’s official stage-to-flow curve, whole and ascending.
Parameters
Section titled “Parameters”gaugeId
Section titled “gaugeId”string
FetchWithRetryOptions = {}
Returns
Section titled “Returns”Promise<DataResult<HazardRatingCurveV1>>
Remarks
Section titled “Remarks”Runs in a browser and in Node. Mirrors Python
mostlyright.weather.hazards.rating_curve(...) and returns
DataResult<HazardRatingCurveV1> stamped "nwps.rating_curve.live",
ascending by stage_ft.
This route serves cubic feet per second, which is what makes flow_cfs here
directly comparable to a gauge’s *_flow_cfs flood threshold.
The ascending order is established here rather than inherited: the route was measured serving the curve that way, but nothing upstream enforces it, and a curve out of order silently breaks a caller interpolating across it.
Throws
Section titled “Throws”ContractError when gaugeId is not addressable, or when the payload
reports flow in a unit the shared table does not convert.
Throws
Section titled “Throws”NotFoundError when gaugeId addresses no gauge.
Example
Section titled “Example”const curve = await ratingCurve("ABBG1");curve.rows.slice(0, 10).map((row) => [row.stage_ft, row.flow_cfs]);sourceTag()
Section titled “sourceTag()”sourceTag(
source):LiveSourceTag
Map a validated source name to its canonical row-level identity tag.
Parameters
Section titled “Parameters”source
Section titled “source”"awc" | "iem"
Returns
Section titled “Returns”stageAndFlow()
Section titled “stageAndFlow()”stageAndFlow(
gaugeId,opts):Promise<DataResult<HazardStageAndFlowV1>>
Return a gauge’s observed and/or forecast stage-and-flow points.
Parameters
Section titled “Parameters”gaugeId
Section titled “gaugeId”string
StageAndFlowOptions = {}
Returns
Section titled “Returns”Promise<DataResult<HazardStageAndFlowV1>>
Remarks
Section titled “Remarks”With no series the combined document is read and BOTH products come back in
one result, discriminated by the series column. With one, only that block is
read.
Runs in a browser and in Node. Mirrors Python
mostlyright.weather.hazards.stage_and_flow(...) and returns
DataResult<HazardStageAndFlowV1> stamped "nwps.stage_and_flow.live",
observed rows first.
flow_kcfs is the verbatim upstream number and flow_cfs the converted one:
this route serves KILO-cubic-feet per second while the gauge threshold and
rating routes serve cubic feet per second, so only flow_cfs is comparable to
a *_flow_cfs threshold.
CAPTURE-OR-LOSE: exactly one forecast issuance is ever served and no route parameter asks for a prior one. A gauge with no current forecast answers HTTP 200 with a zero-valued block and yields ZERO rows — fewer than one gauge in four carries a live forecast at any moment, so that is the ordinary answer, not an error.
Throws
Section titled “Throws”ContractError when series is not one of the two the route serves, or
when gaugeId is not addressable.
Throws
Section titled “Throws”NotFoundError when gaugeId addresses no gauge.
Example
Section titled “Example”const both = await stageAndFlow("ABBG1");both.rows.filter((row) => row.series === "forecast");stream()
Section titled “stream()”stream(
station,opts):AsyncGenerator<LiveObservation>
Yield fresh observations for station from a single source on a
polite-floor cadence.
The loop:
- Validate
source+pollSeconds(throws before the first poll). - Poll once.
- If the most-recent observation’s
event_time_utcdiffers from the last one yielded, yield it. Otherwise skip (dedup). await sleep(pollSeconds).- Loop.
Empty responses (network error, fetcher returned []) do not abort the
stream — they’re treated as “nothing fresh yet” and the loop continues
after the polite-floor sleep. To get a single-shot failure path, use
latest.
Parameters
Section titled “Parameters”station
Section titled “station”string
StreamOptions = {}
Returns
Section titled “Returns”AsyncGenerator<LiveObservation>
Throws
Section titled “Throws”Error before the first poll when opts.source is unsupported
or opts.pollSeconds is below the polite floor.
textProducts()
Section titled “textProducts()”textProducts(
opts):Promise<DataResult<HazardTextProductV1>>
Fetch NWS/NHC text bulletins as rows, with the verbatim text preserved.
Mirrors Python mostlyright.weather.hazards.text_products(...). Returns
DataResult<HazardTextProductV1>: snake_case rows plus the provenance
envelope whose source is the tag of the leg that answered
("nws.text_products.live" or "iem.afos.archive"). Every row carries the
same tag in its own source column and the untouched bulletin in raw_afos,
so a better parser can be run over the same bytes later.
Route choice: source: "nws" or "iem" pins a route. Left unset, a
fromTime older than the live route’s 7-day retention auto-routes to the
Iowa State AFOS archive — a route change, never a rejection.
Parameters
Section titled “Parameters”TextProductsOptions = {}
Returns
Section titled “Returns”Promise<DataResult<HazardTextProductV1>>
Throws
Section titled “Throws”NoHazardDataError when productId names a product that yields no
bulletin text, or when a listed product serves none.
Throws
Section titled “Throws”ContractError when the archive route is asked for without a window, or when the window spans more days than the archive walk will issue.
tropicalCyclones()
Section titled “tropicalCyclones()”tropicalCyclones(
opts):Promise<DataResult<HazardTropicalCycloneV1>>
Fetch the storms NHC currently lists as active.
Parameters
Section titled “Parameters”Returns
Section titled “Returns”Promise<DataResult<HazardTropicalCycloneV1>>
Remarks
Section titled “Remarks”Node-only. www.nhc.noaa.gov sends no Access-Control-Allow-Origin header
(measured 1 August 2026); calling this from a browser page will fail CORS,
so this verb refuses there with a typed ContractError rather than letting
a CORS TypeError surface. A Node process, a Cloudflare Worker, or an
extension service worker with www.nhc.noaa.gov in host_permissions can
call it.
Mirrors Python mostlyright.weather.hazards.tropical_cyclones(...). Returns
DataResult<HazardTropicalCycloneV1> stamped "nhc.tropical_cyclones.live".
A quiet season resolves to an empty result, not an error: upstream serves the
activeStorms container unconditionally, so “no storms” is a fact about the
world rather than a broken request.
validatePollSeconds()
Section titled “validatePollSeconds()”validatePollSeconds(
pollSeconds,source):number
Apply the polite-floor invariant to a caller-supplied cadence.
Parameters
Section titled “Parameters”pollSeconds
Section titled “pollSeconds”Caller-supplied cadence. undefined/null → use the floor.
undefined | null | number
source
Section titled “source”A validated source name (call validateSource first).
"awc" | "iem"
Returns
Section titled “Returns”number
The cadence to use, in seconds.
Throws
Section titled “Throws”Error when pollSeconds is below the polite floor.
validateSource()
Section titled “validateSource()”validateSource(
source):"awc"|"iem"
Normalize and validate a source option.
Parameters
Section titled “Parameters”source
Section titled “source”Caller-supplied source string. undefined/null defaults
to the first entry in SUPPORTED_SOURCES (AWC). Case-insensitive.
undefined | null | string
Returns
Section titled “Returns”"awc" | "iem"
The normalized lowercase source name (one of SUPPORTED_SOURCES).
Throws
Section titled “Throws”Error when the source is not in SUPPORTED_SOURCES.
waterObservations()
Section titled “waterObservations()”waterObservations(
gaugeId,fromTime,toTime,opts):Promise<DataResult<HazardWaterObservationV1>>
Return USGS continuous water values for one site over one window.
Parameters
Section titled “Parameters”gaugeId
Section titled “gaugeId”string
A USGS site number in either spelling: the bare "02215260"
the water-prediction service carries, or the "USGS-02215260" this API
addresses. Both canonicalize to the BARE number, which is what every row’s
gauge_id carries — so one reading is never stored under two identities.
Anything that is not eight to fifteen digits throws before any request.
fromTime
Section titled “fromTime”Date
Window start.
toTime
Section titled “toTime”Date
Window end, at or after fromTime.
Returns
Section titled “Returns”Promise<DataResult<HazardWaterObservationV1>>
Remarks
Section titled “Remarks”Resolves the site ONCE — one monitoring-locations request per call, never
one per page — to validate it and to read the standard-time abbreviation and
daylight-saving flag every returned row is stamped with, then walks the
continuous collection over the window.
Runs in a browser and in Node. Mirrors Python
mostlyright.weather.hazards.water_observations(...) and returns
DataResult<HazardWaterObservationV1> stamped "usgs.waterdata.live". A
VALIDATED site that recorded nothing in the window returns an EMPTY result;
an unknown site throws.
USGS marks recent values Provisional and flips them to Approved roughly
60 to 90 days later. That flip can change the VALUE, not only the label, and
it republishes the same instant under a newer last_modified_at_utc — so a
re-fetch of an unrevised row is idempotent while a revision APPENDS beside the
earlier reading. This is the only flood product whose vintage comes from
upstream.
Throws
Section titled “Throws”ContractError when the window is inverted, when approvalStatus is
not a state USGS publishes, or when the site number is unusable.
Throws
Section titled “Throws”NotFoundError when gaugeId addresses no monitoring location.
Example
Section titled “Example”const day = await waterObservations( "02215260", new Date(Date.UTC(2026, 7, 1)), new Date(Date.UTC(2026, 7, 2)),);day.rows.map((row) => [row.valid_at_utc, row.value, row.approval_status]);wildfires()
Section titled “wildfires()”wildfires(
opts):Promise<DataResult<HazardWildfireV1>>
Return wildfire incident records — national interagency, or California state.
Parameters
Section titled “Parameters”WildfiresOptions = {}
Returns
Section titled “Returns”Promise<DataResult<HazardWildfireV1>>
Remarks
Section titled “Remarks”With no arguments this is the current national wildfire picture: the
interagency current service, wildfires only, complex children excluded,
every row stamped "wfigs.current.live".
BROWSER + NODE on the default leg. wildfires({ source: "calfire" }) is
NODE-ONLY — incidents.fire.ca.gov sends no Access-Control-Allow-Origin
header (measured 1 August 2026), so a browser page is refused at call time
with a typed ContractError rather than an opaque CORS failure. See
docs/browser-integration.md.
Mirrors Python mostlyright.weather.hazards.wildfires(...) and returns
DataResult<HazardWildfireV1> tagged with the leg that answered:
"wfigs.current.live", "wfigs.season.live", "wfigs.history", or
"calfire.incidents.live".
The interagency season and history windows are the operational record:
the publisher states that they represent “a snapshot in time of what was
known for each incident during the operational period of the fire” and are
“not QA/QC’d after a fire is declared out”. The certified record lives on a
different service, which this tier catalogs and does not read.
persist is Python-only; see ./wildfires.types.ts.
Throws
Section titled “Throws”ContractError when source is unknown, when an argument belongs to
the other leg (the message names that leg), when a value would reach the query
clause in an unchecked shape, or when a history walk exceeds
WFIGS_HISTORY_ROW_CEILING — measured on every history call, bounded or
not, because a date bound is not a size.
Throws
Section titled “Throws”HazardRetentionError when fromDate or toDate predates what
scope: "current" can answer — a window is historical when either end of it
is. It never returns a short frame.
Throws
Section titled “Throws”SourceUnavailableError when a service answers HTTP 200 with an error object, or when the state route answers a season with another season’s rows.
Throws
Section titled “Throws”ApiKeyRequiredError when no API key is configured for catalog resolution.
Example
Section titled “Example”const burning = await wildfires();burning.rows.map((row) => [row.incident_name, row.acres, row.percent_contained]);
const california = await wildfires({ source: "calfire", year: 2025 });