Skip to content

Observation schema

Every row returned by observations() carries the same 30 fields. Live or historical, JSON or parquet, one station or many. Column parity is enforced by the specs/observation.json spec shared between the API and the SDK. Any deviation at the source raises SchemaValidationError before it reaches you.

This page is the human-readable reference. The machine-readable contract is at specs/observation.json.

FieldTypeNotes
station_codestring3-letter NWS code, uppercase ("NYC", "ATL")
observed_atstringUTC ISO-8601 timestamp of the observation
observation_typestring"METAR" or "SPECI" (special, off-hour)

Every row is uniquely keyed by (station_code, observed_at, observation_type). No duplicates, no silent overwrites. See Raw-as-reported.

FieldTypeNotes
sourcestring"AWC", "IEM", or "GHCNh". Which pipeline produced the row.

See Data sources for priority rules.

FieldTypeUnitNullableNotes
temp_ffloat°FNoStored unrounded, e.g. 72.3.
temp_cfloat°CNoDerived from temp_f.
dewpoint_ffloat°FYesMissing on some older METARs.
dewpoint_cfloat°CYes

Temperatures are never rounded to integers in storage. If your settlement logic needs a rounded integer, round at read time. The raw value is always available.

FieldTypeUnitNotes
wind_dir_degreesintdegrees true0 through 360, null for variable winds.
wind_speed_ktintknotsInteger knots. See raw_metar for decimal.
wind_gust_ktintknotsNull when no gust was reported.

Winds are in knots because METARs are in knots. Convert to mph or m/s client-side if needed.

FieldTypeUnitNotes
peak_wind_gust_ktintknotsPeak gust since the last report. Null if not given.
peak_wind_dirintdegrees trueDirection of the peak gust.
peak_wind_timestringUTC timeISO-8601 timestamp of the peak gust.

Peak wind fields are populated when a METAR includes a PK WND group and are null otherwise.

FieldTypeUnitNotes
altimeter_inhgfloatinHgAltimeter setting, e.g. 30.12.
sea_level_pressure_mbfloatmbSea-level pressure, null on many METARs. (1 mb = 1 hPa.)

altimeter_inhg is the altimeter setting, not MSL pressure. For MSL pressure use sea_level_pressure_mb when non-null.

METAR reports up to four cloud layers. Lower layer slots are populated first. Use sky_cover_1 as the lowest significant layer for quick checks.

FieldTypeUnitNotes
sky_cover_1stringFirst layer: "CLR", "SCT", "BKN", or "OVC".
sky_base_1_ftintfeetBase of layer 1, AGL.
sky_cover_2stringSecond layer, null if absent.
sky_base_2_ftintfeetBase of layer 2, AGL.
sky_cover_3stringThird layer, null if absent.
sky_base_3_ftintfeetBase of layer 3, AGL.
sky_cover_4stringFourth layer, null if absent.
sky_base_4_ftintfeetBase of layer 4, AGL.
FieldTypeUnitNotes
visibility_milesfloatmilesStatute miles.
weather_codesstringRaw METAR weather code string, e.g. "RA BR".

weather_codes is the raw METAR code string, not a translation. If you need “rain” or “snow” booleans, derive them from this column client-side.

FieldTypeUnitNotes
precip_1hr_inchesfloatinchesPast 1 hour ending at observed_at, null if missing.

Precipitation is cumulative across the last hour ending at observed_at. Not always populated; some stations only report during precipitation events.

FieldTypeUnitNotes
snow_depth_inchesfloatinchesCurrent snow depth on the ground.
FieldTypeNotes
qc_fieldstringQuality-control marker from the source pipeline, nullable.
raw_metarstringFull raw METAR string as broadcast.

raw_metar is the ground truth. Everything else in the row is a parse of it. If our parse is wrong, raw_metar lets you re-parse yourself. If you are building a model on the decoded fields, cross-check against raw_metar in training. It is the most honest signal the row carries.

  • Identity (3): station_code, observed_at, observation_type
  • Source (1): source
  • Temperature (4): temp_f, temp_c, dewpoint_f, dewpoint_c
  • Wind (3): wind_dir_degrees, wind_speed_kt, wind_gust_kt
  • Peak wind (3): peak_wind_gust_kt, peak_wind_dir, peak_wind_time
  • Pressure (2): altimeter_inhg, sea_level_pressure_mb
  • Sky cover (8): sky_cover_1/2/3/4, sky_base_1_ft/2_ft/3_ft/4_ft
  • Visibility and weather (2): visibility_miles, weather_codes
  • Precipitation (1): precip_1hr_inches
  • Snow (1): snow_depth_inches
  • Provenance (2): qc_field, raw_metar

Thirty fields, sourced from the specs/observation.json contract. New fields ship behind an opt-in features selector first, then move to everyone on the next minor version.