---
title: "Describe one data catalog product."
method: GET
path: "/v1/catalog/{product_id}"
tags: ["Meta"]
---

# Describe one data catalog product.

`GET /v1/catalog/{product_id}`

## Request

- Base URL: `https://api.smarterweather.com`
- URL: `https://api.smarterweather.com/v1/catalog/{product_id}`
- Auth: HTTP bearer

Returns one product of the data catalog: the `GET /v1/catalog`
fields plus its `agent_description`, `aliases`, `question_shapes`,
`related` products and `variables` (names, standard names, units,
display units, valid range, thresholds, categories and bands).

`include=freshness` adds the product's `freshness`
(**experimental**), as on the list. Caching, auth and cost are as
on `GET /v1/catalog`, including the `ETag` and `304` without
`include=freshness`.

An id that is not in the catalog, or not served on the REST API,
returns `404`.

## Path parameters

- `product_id` string, required

## Query parameters

- `include` string

## Response `200`

The product.

- CatalogProduct: A data catalog product, as listed by `GET /v1/catalog`.
  - `id` string, required: Product id, the `product` of `/v1/point` and the MCP `dataset_id`.
  - `title` string, required
  - `family` string, required: Product family, e.g. `nbm`, `mrms`, `spc`.
  - `kind` string, required: Data shape: `grid` (a gridded field over time), `snapshot` (the latest gridded analysis), `feature` (vector features such as outlook polygons) or `text` (text products). New kinds may be added.
  - `product_type` string, nullable, required: `forecast`, `analysis` or `climatology`; `null` when the catalog does not classify the product. New values may be added.
  - `domain` string, required: Coverage domain, e.g. `conus`, `alaska`, `hawaii`, `global`.
  - `coverage` string[], required: Domains the product covers.
  - `cadence` string, nullable, required: Nominal update cadence, an ISO 8601 duration.
  - `horizon` string, nullable, required: Forecast horizon, an ISO 8601 duration; `null` for analyses.
  - `step` string, nullable, required: Native frame spacing, an ISO 8601 duration: how far apart the product's frames are (`PT6H` for a 6-hourly model, `PT2M` for an MRMS mosaic, `P1D` for a daily product). Set on every `grid` and `snapshot` product; `null` for `feature` and `text` products, which have no frames. A sub-day step divides 24 h and a longer one is whole days. A rolling `/v1/series` forecast window starts at now floored to it from 00:00Z (a step of a day or more floors to UTC midnight), so the frame covering now is in.
  - `temporal_type` string, nullable, required: How the product is stored in time: `now`, `hourly`, `daily` or `climatology`. New values may be added.
  - `grid_res_km` number, double, nullable, required: Grid spacing in kilometres; `null` for non-gridded products.
  - `stability` string, required: Catalog stability of the product, `stable`, `beta` or `experimental`.
  - `cost_class` string, required: Cost class of the product's data calls.
  - `entitlement` string, nullable, required: Entitlement label the product requires; `null` when none.
  - `source` CatalogSource, required: The product's data source and attribution terms.
    - `id` string, required
    - `name` string, nullable, required
    - `provider_id` string, required
    - `attribution` string, required: Attribution text to display with the data.
    - `license` string, required
    - `terms_url` string, nullable, required
  - `freshness` object, nullable: **Experimental** (`x-stability: experimental`). How current a product's data is, as the MCP `list_datasets` tool reports it. The shape is final; the values' sources are still being completed: freshness checks cover a fixed set of products today, so some products (for example untracked analyses) have `freshness: null` and an untracked forecast has a `latest_run` but no `freshness_status`. Values are refreshed at most once a minute; while the freshness source is unavailable the last values are kept for up to 5 minutes (`data_age_seconds` is computed when the response is made, so it still shows how old the data is), then `freshness` is `null`.
    - `freshness_status` 'fresh' | 'stale' | 'missing': The platform's freshness check for the product: `fresh` within its expected age, `stale` older, `missing` no data found. When a product is checked in more than one store, the stalest result. Absent when the product is not checked.
    - `latest_time` string, date-time: Valid time of the newest data the freshness check found.
    - `latest_run` string, date-time: Reference time of the latest model run served (forecasts only).
    - `data_age_seconds` integer, nullable, required: Age of the newest data in seconds: from `latest_run` for a forecast, else from `latest_time`. `null` when unknown or when the time is in the future (a forecast valid time says nothing about age).
  - `agent_description` string, nullable, required: Plain-language description of what the product answers.
  - `aliases` string[], required: Search phrases the product answers to.
  - `question_shapes` string[], required: Example questions the product answers.
  - `related` string[], required: Ids of related catalog products.
  - `variables` CatalogVariable[], required
    - `name` string, required: Stored variable name, as the data files name it; accepted as an alias of `standard_name` on `/v1/point` and `/v1/series`.
    - `standard_name` string, required: Standard variable name, the public identifier on every door: the `var` of `/v1/point` and `/v1/series`, the MCP `query_dataset` `variables`, and the key of every `values` and `units` map.
    - `label` string, nullable, required
    - `description` string, nullable, required
    - `units` string, nullable, required: Units of the stored values.
    - `display_units` object, required
      - `conversion` string, required: `absolute` for a value, `delta` for a difference (converted without an offset). New values may be added.
      - `metric` string, nullable, required
      - `imperial` string, nullable, required
    - `kind` string, required: `deterministic`, `probability`, `percentile`, `stddev` or `category`. New values may be added.
    - `threshold` object, nullable, required: The event a probability variable measures; `null` otherwise.
      - `op` string, required
      - `value` number, double, required
      - `units` string, required
    - `period` string, nullable, required: Accumulation or aggregation period, an ISO 8601 duration.
    - `min` number, double, nullable, required: Lower bound of valid values, in `units`.
    - `max` number, double, nullable, required: Upper bound of valid values, in `units`.
    - `aliases` string[], required
    - `categories` object[], required: Value buckets in ascending `max` order; the last bucket has `max: null` (the catch-all).
      - `max` number, double, nullable, required
      - `label` string, required
    - `bands` object[], required: Categorical codes and their public levels (outlook risk bands).
      - `code` string, required
      - `level` integer, required
      - `category` string, required
      - `label` string, required
    - `point` object, nullable, required: How `/v1/point` serves the variable: the `unit` it reports (`null` for a categorical zone). `null` when `/v1/point` does not serve the variable.
      - `unit` string, nullable, required

## Other responses

- `304`: The `If-None-Match` tag matches the current catalog: no body. The `ETag` and `Cache-Control` headers are repeated.
- `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.
- `404`: No catalog product with this id is served on the REST API.
- `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.

---

[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)
