---
title: "Growing Degree Units (GDU / GDD) for a point."
method: GET
path: "/v1/agriculture/growing-degree-days"
tags: ["Agriculture"]
---

# Growing Degree Units (GDU / GDD) for a point.

`GET /v1/agriculture/growing-degree-days`

## Request

- Base URL: `https://api.smarterweather.com`
- URL: `https://api.smarterweather.com/v1/agriculture/growing-degree-days`
- Auth: HTTP bearer

Returns Growing Degree Units (also called Growing Degree Days) for a
US point (CONUS, Alaska, Hawaii), computed on read from stored daily
maximum/minimum temperatures. No GDU grids are stored; the values are
derived per request from the temperature bundles, so a crop's
base/upper thresholds and the simple/modified method can be selected
freely without re-running the pipeline.

**Two modes:**

- **Forecast (default).** Without `season_start`, the response carries
  a per-day GDU series across the NBM forecast horizon (`days`).
- **Season cumulative.** With `season_start` (a `YYYY-MM-DD` local
  date within the ~180-day observed window), the response stitches
  RTMA observed daily history + today's partial (hourly on-read
  rollup) + NBM forecast, returns a `cumulative_total`, and adds a
  per-day `cumulative_gdu` running sum. This is the number a grower
  tracks against crop growth-stage milestones. If part of the season
  window has no observed data, the per-day series still comes back
  `200` but `cumulative_total` is omitted and `meta.gaps` carries an
  `unfilled` span — a partial sum is not a season total.

**Crops.** Pass a catalog `crop` id (e.g. `corn`, `soybean`,
`wheat_winter`, `cotton`, `alfalfa`) to use calibrated thresholds, or
`crop=custom` with `base_temp_c` (and optionally `upper_temp_c` /
`method`) to supply your own.

Every response echoes the resolved `method`, `thresholds` (always in
°C), and a `meta` provenance block (`day_definition`,
`computation_path`, `source`, `unit`, any `gaps`) so nothing is
silently assumed.

Pass one location: `lat` and `lon`, `zip`, or `location`. A request
without one returns `400`; a ZIP or name that does not resolve
returns `404`; while location lookup is unavailable, a `zip` or
`location` request returns `503` with `Retry-After`.
The resolved place is echoed as `location`, present when the place
was resolved.

A point outside the 50 US states and DC returns `404`
`outside-coverage` with `next_steps`.

## Query parameters

- `lat` number, double
- `lon` number, double
- `zip` string
- `location` string
- `crop` string, required
- `season_start` string, date
- `days` integer
- `day_definition` 'nws' | 'local_calendar'
- `unit` 'imperial' | 'metric'
- `base_temp_c` number, double
- `upper_temp_c` number, double
- `method` 'simple' | 'modified'
- `include_milestones` boolean

## Response `200`

Growing Degree Units for the requested point.

- GrowingDegreeDays: Growing Degree Units for a point, forecast or season-cumulative.
  - `crop` string, required: Echoed crop id (`corn`, ..., or `custom`).
  - `catalog_version` integer, required: Version of the crop catalog used to resolve thresholds.
  - `method` 'simple' | 'modified', required: GDU method applied.
  - `thresholds` GddThresholds, required: Resolved GDU thresholds, always expressed in °C.
    - `base_temp_c` number, double, required: Base (lower) temperature threshold in °C.
    - `upper_temp_c` number, double: Upper cutoff in °C (present only for the modified method).
  - `meta` GddMeta, required: Provenance for a GDU response. Nothing is silently assumed.
    - `day_definition` 'nws' | 'local_calendar', required: The daily boundary used.
    - `computation_path` string, required: How the series was assembled (e.g. forecast-only vs. stitched observed + partial + forecast), for grid-vs-point transparency.
    - `source` string, required: Backing product mix (NBM / RTMA) used for this answer.
    - `freshness` string: Human-readable data-age hint, when available.
    - `unit` 'imperial' | 'metric', required: Unit system applied to numeric GDU + temperature fields.
    - `approximate` boolean: True when gaps were interpolated or coverage was partial.
    - `gaps` GddGap[]: Missing-day runs affecting a cumulative total.
      - `start` string, date, required: First missing day (inclusive).
      - `end` string, date, required: Last missing day (inclusive).
      - `days` integer, required: Number of missing days in the run.
      - `filled` string, required: How the gap was handled, e.g. `interpolated` (short gap filled from adjacent days) or `unfilled` (long gap surfaced, not silently under-counted).
  - `days` GddDay[], required: Per-day GDU series (chronological).
    - `date` string, date, required: Local calendar date for this day.
    - `gdu` number, double, required: GDU accrued on this day, in the requested unit.
    - `tmax_c` number, double: Daily maximum temperature in °C (metric responses).
    - `tmin_c` number, double: Daily minimum temperature in °C (metric responses).
    - `tmax_f` number, double: Daily maximum temperature in °F (imperial responses).
    - `tmin_f` number, double: Daily minimum temperature in °F (imperial responses).
    - `cumulative_gdu` number, double: Running season-to-date total through this day. Present only in cumulative mode (when `season_start` was supplied).
    - `missing` boolean: True when the underlying day had no temperature data.
    - `interpolated` boolean: True when this day's value was interpolated across a gap.
  - `cumulative_total` number, double: Season-to-date GDU total in the requested unit. Present only in cumulative mode (when `season_start` was supplied), and omitted even then when `meta.gaps` contains an `unfilled` span: those days have no observed data, so the sum would under-count the season. Treat an absent total on a `season_start` request as "season total unavailable" and fall back to the per-day series, which is still good for the days it covers. `meta.gaps` names the window that was lost.
  - `milestones` GddMilestone[]: Crop growth-stage GDU hints, present when `include_milestones=true` and the crop has catalog milestones.
    - `stage` string, required: Growth-stage label (e.g. `emergence`, `silking`).
    - `gdu` number, double, required: Cumulative GDU (requested unit) at which the stage is reached.
  - `location` Location: Resolved location.
    - `lat` number, double, required
    - `lon` number, double, required
    - `name` string, required: Human-readable place name, usually without the state; see `region`. The resolved place name, else the city, else the nearest city. Empty when none is known.
    - `region` string: State or region abbreviation.
    - `country` string: ISO 3166-1 alpha-2 country code.
    - `timezone` string, required: IANA timezone identifier.
    - `county` string: County name (US only).
    - `zip` string: ZIP code (US only).

## 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.
- `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)
