Observation schema
Every observation row carries the same 30 fields. Live or historical, JSON or parquet, one station or many. Column parity is enforced inside the SDK by the observation.json schema vendored from the source repo. Any deviation at the source raises SchemaValidationError before it reaches you.
This page is the human-readable reference. The machine-readable schema lives in the SDK source on GitHub.
01 · Identity
Section titled “01 · Identity”| Field | Type | Notes |
|---|---|---|
station_code | string | 3-letter NWS code, uppercase ("NYC", "ATL") |
observed_at | string | UTC ISO-8601 timestamp of the observation |
observation_type | string | "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.
02 · Source
Section titled “02 · Source”| Field | Type | Notes |
|---|---|---|
source | string | "AWC", "IEM", or "GHCNh". Which pipeline produced the row. |
See Data sources for priority rules.
03 · Temperature
Section titled “03 · Temperature”| Field | Type | Unit | Nullable | Notes |
|---|---|---|---|---|
temp_f | float | °F | No | Stored unrounded, e.g. 72.3. |
temp_c | float | °C | No | Derived from temp_f. |
dewpoint_f | float | °F | Yes | Missing on some older METARs. |
dewpoint_c | float | °C | Yes |
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.
04 · Wind
Section titled “04 · Wind”| Field | Type | Unit | Notes |
|---|---|---|---|
wind_dir_degrees | int | degrees true | 0 through 360, null for variable winds. |
wind_speed_kt | int | knots | Integer knots. See raw_metar for decimal. |
wind_gust_kt | int | knots | Null when no gust was reported. |
Winds are in knots because METARs are in knots. Convert to mph or m/s client-side if needed.
05 · Peak wind
Section titled “05 · Peak wind”| Field | Type | Unit | Notes |
|---|---|---|---|
peak_wind_gust_kt | int | knots | Peak gust since the last report. Null if not given. |
peak_wind_dir | int | degrees true | Direction of the peak gust. |
peak_wind_time | string | UTC time | ISO-8601 timestamp of the peak gust. |
Peak wind fields are populated when a METAR includes a PK WND group and are null otherwise.
06 · Pressure
Section titled “06 · Pressure”| Field | Type | Unit | Notes |
|---|---|---|---|
altimeter_inhg | float | inHg | Altimeter setting, e.g. 30.12. |
sea_level_pressure_mb | float | mb | Sea-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.
07 · Sky cover
Section titled “07 · Sky cover”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.
| Field | Type | Unit | Notes |
|---|---|---|---|
sky_cover_1 | string | First layer: "CLR", "SCT", "BKN", or "OVC". | |
sky_base_1_ft | int | feet | Base of layer 1, AGL. |
sky_cover_2 | string | Second layer, null if absent. | |
sky_base_2_ft | int | feet | Base of layer 2, AGL. |
sky_cover_3 | string | Third layer, null if absent. | |
sky_base_3_ft | int | feet | Base of layer 3, AGL. |
sky_cover_4 | string | Fourth layer, null if absent. | |
sky_base_4_ft | int | feet | Base of layer 4, AGL. |
08 · Visibility and weather
Section titled “08 · Visibility and weather”| Field | Type | Unit | Notes |
|---|---|---|---|
visibility_miles | float | miles | Statute miles. |
weather_codes | string | Raw 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.
09 · Precipitation
Section titled “09 · Precipitation”| Field | Type | Unit | Notes |
|---|---|---|---|
precip_1hr_inches | float | inches | Past 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.
10 · Snow
Section titled “10 · Snow”| Field | Type | Unit | Notes |
|---|---|---|---|
snow_depth_inches | float | inches | Current snow depth on the ground. |
11 · Provenance
Section titled “11 · Provenance”| Field | Type | Notes |
|---|---|---|
qc_field | string | Quality-control marker from the source pipeline, nullable. |
raw_metar | string | Full 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.
12 · Field groups at a glance
Section titled “12 · Field groups at a glance”- 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.
Related
Section titled “Related”- SDK overview for how to query these fields via the local-first SDK.
- Raw-as-reported for why there is no
corrected_atcolumn. - Data sources for what
sourceactually means.