---
title: "Curated point value(s) for allowlisted stored data."
method: GET
path: "/v1/point"
tags: ["Products"]
---

# Curated point value(s) for allowlisted stored data.

`GET /v1/point`

## Request

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

Returns the value in effect now of allowlisted stored data sampled at
a point: the latest frame of an analysis, or the forecast frame whose
period contains now, from the newest run that has one (HeatRisk:
today's level; `unavailable` when no frame covers now). Output is
friendly (canonical `unit`, an optional `category` label,
`observed_at`, and a staleness flag). The other days of a forecast
are on `GET /v1/series`.

This is the one curated point lookup over stored data: it serves
only the `(product, var)` pairs on a server-side **allowlist**, so the
public surface stays safe and small while every widget/card is
onboarded by adding an allowlist entry — no new endpoint. The
allowlist is every variable with point metadata on a product of the
data catalog (`GET /v1/catalog`). Requesting a
`(product, var)` that is not allowlisted returns `404` (single form) or
a per-item `not_allowlisted` status (batch form).

### Data kinds (transparent to the caller)

The allowlist entry's kind selects how the point is resolved — a
**scalar** grid cell, or a vector **zone** (point-in-polygon
outlook, e.g. SPC categorical / fire-weather). Both collapse to one
answer at a location and share one envelope: `value`/`unit` are present
for scalars and ordinal bands, `category`/`label` name the band, and a
point in no band is a valid answer with `value: null` and
`category: "none"` (not a 404).

### Single vs. batch

- **Single** — `product` + `var` + `lat` + `lon` returns one
  `PointValue`.
- **Batch** — `select` (multiple `(product, var)`) and/or `points`
  (multiple locations) returns a `PointBatchResponse` of per-point,
  per-value items, each with a `status`. One request can populate a
  whole family card (several metrics) or a map of locations; partial
  conditions (out of domain, not allowlisted, no data) are reported
  per item and never fail the whole request.

### Coverage

Coverage is the 50 US states and DC. A single point outside it gets
the `404` `outside-coverage` problem with `next_steps`; in a batch
such a point is `out_of_domain` for every selector, as is a batch
point the check could not reach within its time limit (retry it; the
lookup carries on and caches). A point outside
every US model grid is rejected without an upstream call; one inside
a grid but outside the 50 states and DC (Canada, Mexico, open water)
is rejected after a cached reverse geocode. Each allowlisted entry
also carries a coverage domain; a covered point outside it returns
the plain `404` (single) or an `out_of_domain` item (batch). Scalar values are sampled from the nearest grid cell
(products are snapped to a ~1 km grid), so nearby requests share cache
entries.

### Staleness

`approximate` is `true` when the value is older than the product's update
cadence allows (e.g. a SPoRT-LIS daily analysis older than ~36 h, an
MRMS hourly accumulation older than ~3 h). A forecast's age is that of
the run it is served from: HeatRisk is `approximate` when that run is
older than ~36 h.

### Caching

Successful responses carry `Cache-Control` with a `max-age` keyed to the
product's cadence (SPoRT-LIS daily: 30 min; MRMS QPE hourly: 5 min). The
service additionally caches by `(product, var, rounded lat/lon)`.

### Auth

Standard sw-api Bearer auth applies.

## Query parameters

- `product` string
- `var` string
- `lat` number, double
- `lon` number, double
- `select` string[]
- `points` string[]

## Response `200`

The requested value(s). Single form (`product`+`var`+`lat`+`lon`)
returns a `PointValue`; batch form (`select` and/or `points`)
returns a `PointBatchResponse`.

- union
  - PointValue: A single allowlisted value sampled at a point, with friendly metadata. The single-form wire shape for GET /v1/point (scalar or zone).
    - `product` string, required: Echoed product identifier.
    - `var` string, required: The `var` as sent (`standard_name` or the stored `name`).
    - `value` number, double, nullable, required: The sampled value in `unit` (scalar), or the ordinal level of the containing band (zone). `null` when a zone point is in no band (`category: "none"`).
    - `unit` string: Canonical unit of `value` (clients convert for display).
    - `category` string: Optional human category the value falls into (e.g. soil-moisture `dry`/`normal`/`moist`, or an outlook band like `slight`). The explicit value `"none"` means a zone point is in no band. Omitted for scalars without categories.
    - `label` string: Optional human display label for a named band (e.g. `Slight`, `Elevated`). Omitted for plain scalars.
    - `observed_at` string, date-time: Valid time of the sampled value / outlook.
    - `approximate` boolean, required: True when the value is older than the product's update cadence allows (stale).
    - `status` 'ok' | 'unavailable': Outcome of the point query. `ok` when a value is present; `unavailable` when no sample exists at the location (within domain).
  - PointBatchResponse: The batch-form wire shape for GET /v1/point: per-point, per-selector values. Returned when `select` and/or `points` is provided.
    - `results` PointBatchResult[], required: One entry per requested point, in request order.
      - `lat` number, double, required: Echoed latitude of the requested point.
      - `lon` number, double, required: Echoed longitude of the requested point.
      - `values` PointValueItem[], required: One item per requested selector, in request order.
        - `product` string, required: Echoed product identifier.
        - `var` string, required: The selector's `var` as sent (`standard_name` or the stored `name`).
        - `value` number, double, nullable: The sampled value / band ordinal. Omitted for non-`ok` items and `null`/omitted for a zone point in no band.
        - `unit` string: Canonical unit of `value` (clients convert for display).
        - `category` string: Human category (or `"none"` for a zone point in no band). Omitted when not applicable.
        - `label` string: Human display label for a named band. Omitted otherwise.
        - `observed_at` string, date-time: Valid time of the sampled value / outlook.
        - `approximate` boolean, required: True when the value is stale for its cadence.
        - `status` 'ok' | 'not_allowlisted' | 'out_of_domain' | 'unavailable', required: Per-item outcome. `ok` — resolved (a zone `"none"` is still `ok`). `not_allowlisted` — the selector is not curated. `out_of_domain` — the point is outside the product's coverage (including a point outside lat [-90, 90] / lon [-180, 180]). `unavailable` — no data at the point.

## Other responses

- `400`: Bad request.
- `404`: Resource not found: a location that cannot be resolved (unknown ZIP, unrecognised free-text location), no upstream data for the location, or a missing resource. On a route that checks coverage (its description says so), a location outside the 50 US states and DC returns type `https://smarterweather.com/errors/outside-coverage`; that and the location-not-found problem carry `next_steps` (`recommended = coverage`).
- `502`: Bad gateway. The service received an invalid response from an upstream data source. Transient; clients should retry with backoff.
- `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)
