---
title: "Get NWS daily climate reports as GeoJSON."
method: GET
path: "/v1/climate-reports"
tags: ["Climate"]
---

# Get NWS daily climate reports as GeoJSON.

`GET /v1/climate-reports`

## Request

- Base URL: `https://api.smarterweather.com`
- URL: `https://api.smarterweather.com/v1/climate-reports`
- Auth: HTTP bearer

Returns a GeoJSON `FeatureCollection` of NWS daily climate
reports (CLI): observed high and low, precipitation and snowfall
per station, with departures from normal. Each feature's
`properties` bag carries at minimum `valid_time`; other keys
come from the data pipeline and may be added without a
sw-api release.

**Experimental** (`x-stability: experimental`): excluded from
the 90-day breaking-change commitment. This route serves a
single product. When the generic feature route ships, it
becomes a stable alias of that route with the same shape, or
folds into it.

### Time window

One selector is used, by precedence `date` > `start+end` >
`hours`:

1. `date=YYYY-MM-DD` — reports for one day. It must be a real
   calendar day (`2026-02-30` is a `400`). When `date` is set,
   `start`/`end` are not used, so the ordering and span rules
   below do not apply to them.
2. `start=...&end=...` — RFC 3339 instants, both required.
   Reports are matched by the UTC calendar date of `start` and
   `end`, so both ends are inclusive days
   (`2026-05-01T20:00:00-07:00` is 2026-05-02). `start` must not
   be after `end`, and the span is at most 31 UTC calendar days.
3. `hours=N` — rolling lookback, 1 to 168 (7 days). Default 24.

### Filters

- `wfo` — 3-letter CLI site code, the suffix of the report's
  AWIPS id (`ORD` for `CLIORD`). It names the climate site, which
  is not always the issuing office's identifier.
- `station` — case-insensitive substring of the station name:
  1-64 letters, digits, spaces or `. , ' ( ) / & -`. Other
  characters (including `%`, `_` and `\`) are a `400`.

### Caching

Successful responses carry `Cache-Control: max-age=300,
stale-while-revalidate=300`, `public` for first-party keys and
`private` for partner keys.

### Auth

Standard sw-api Bearer auth applies.

## Query parameters

- `hours` integer
- `date` string
- `start` string, date-time
- `end` string, date-time
- `wfo` string
- `station` string

## Response `200`

GeoJSON FeatureCollection. Empty `features` array when no
reports match.

## Other responses

- `400`: Bad request.
- `401`: Missing or invalid API key. Carries a `WWW-Authenticate` challenge and a `next_steps` extension. `recommended` is `device_flow`: the object is a complete no-install mint recipe.
- `402`: Trial key free value ended (lifetime cap spent or key clock expired) while the claim window is still open. Carries `next_steps.recommended = claim` and the per-key claim href.
- `403`: API key lacks the required scope. Carries a `WWW-Authenticate` challenge with `error="insufficient_scope"` and a `next_steps` extension.
- `429`: Rate limit exceeded. Carries a `next_steps` extension (`recommended: upgrade`, plus `pricing` and `usage`) telling the caller how to lift the limit.
- `500`: Internal server error.
- `502`: Bad gateway. The service received an invalid response from an upstream data source. Transient; clients should retry with backoff.
- `503`: Service unavailable. An upstream dependency is unavailable or shedding load (type `service-unavailable`). Transient; retry with backoff and honor any `Retry-After` header.
- `504`: Gateway timeout. An upstream data source did not respond within the service's budget.

---

[API](https://skmtc.dev/smarterweather/apis/smarter-weather-api.md) · [All operations](https://skmtc.dev/smarterweather/apis/smarter-weather-api/llms.txt) · [OpenAPI document](https://skmtc.dev/smarterweather/apis/smarter-weather-api/revisions/520d55a696e4?raw)
