API reference

Weather

Forecasts, air quality and place search, and your saved places and units.

See Weather. Weather is personal: these routes take no organization, and a key needs weather:read in its own. Show "Weather data by Open-Meteo.com" (the answer's source.attribution, linking to source.url) wherever you show the data.

GET /v1/weather/forecast

The forecast at a point: current conditions, today, hours hourly (1–48, default 24, from the current hour) and days daily (1–16, default 10, from today in the place's time zone), air quality where there is some, and the attribution to show with it. Cached for 10 minutes per 1 km cell. units (metric or imperial) defaults to the person's saved choice. place names the caller's saved place within 1.5 km. 429 (with Retry-After) past the per-person limits.

Auth: user access token or platform agent key · Scope: weather:read

Query parameterTypeRequiredNotes
latnumberYes-90–90; coerced from a string
lonnumberYes-180–180; coerced from a string
units"metric" | "imperial"No
daysintegerNo1–16; coerced from a string
hoursintegerNo1–48; coerced from a string

Response 200

{
  at: number
  timeZone: string
  units: {
    temperature: "C" | "F"
    wind: "km/h" | "mph"
    precipitation: "in" | "mm"
  }
  place?: {
    name: string
    region?: string
    country?: string
  }
  current: {
    temp: number
    feelsLike: number
    humidity: number
    windSpeed: number
    windGust?: number
    windDir: number
    windCompass: string
    pressure?: number
    uv?: number
    precip: number
    cloud: number
    visibility?: number
    isDay: boolean
    code: number
    condition: string
    symbol: string
    icon: "cloud" | "sunny" | "bedtime" | "partly-cloudy-day" | "partly-cloudy-night" | "foggy" | "rainy-light" | "rainy" | "rainy-heavy" | "weather-mix" | "weather-snowy" | "snowing-heavy" | "grain" | "thunderstorm"
  }
  today: {
    high: number
    low: number
    precipChance: number
    precipSum: number
    sunrise: number
    sunset: number
    uvMax?: number
    windMax?: number
  }
  hourly: {
    at: number
    temp: number
    precipChance: number
    precip: number
    code: number
    symbol: string
    icon: "cloud" | "sunny" | "bedtime" | "partly-cloudy-day" | "partly-cloudy-night" | "foggy" | "rainy-light" | "rainy" | "rainy-heavy" | "weather-mix" | "weather-snowy" | "snowing-heavy" | "grain" | "thunderstorm"
    windSpeed: number
    isDay: boolean
  }[]
  daily: {
    date: string
    high: number
    low: number
    precipChance: number
    precipSum: number
    code: number
    condition: string
    symbol: string
    icon: "cloud" | "sunny" | "bedtime" | "partly-cloudy-day" | "partly-cloudy-night" | "foggy" | "rainy-light" | "rainy" | "rainy-heavy" | "weather-mix" | "weather-snowy" | "snowing-heavy" | "grain" | "thunderstorm"
    sunrise: number
    sunset: number
    windMax: number
    uvMax?: number
  }[]
  airQuality?: {
    aqi: number
    pm25?: number
    category: "Good" | "Fair" | "Moderate" | "Poor" | "Very poor" | "Extremely poor"
  }
  source: {
    id: string
    name: string
    attribution: string
    url: string
  }
}

Errors

StatusMessage
400Give lat and lon.

Places by name or postcode, best first (count 1–10, default 5); "Name, region or country" narrows. Each has a placeId (gn: and its GeoNames id) to save it with. Fewer than 2 characters find nothing.

Auth: user access token or platform agent key · Scope: weather:read

Query parameterTypeRequiredNotes
qstringYesup to 100 characters
countintegerNo1–10; coerced from a string

Response 200

{
  results: {
    placeId: string
    name: string
    region?: string
    country?: string
    lat: number
    lon: number
    timeZone?: string
  }[]
}

GET /v1/me/weather/places

Your saved places in your order, and your units (metric until you choose). The same on every device.

Auth: user access token or platform agent key · Scope: weather:read

Response 200

{
  places: {
    placeId: string
    name: string
    region?: string
    country?: string
    lat: number
    lon: number
    timeZone: string
  }[]
  units: "metric" | "imperial"
  updatedAt?: number
}

Errors

StatusMessage
403Saved places belong to people, not keys.

PUT /v1/me/weather/places

Replaces your saved places with places, in order (up to the weather.places limit, 20 by default), and sets units when given. A place without a placeId gets one (wpl_…). Coordinates are kept to 3 decimals. Not from an assistant.

Auth: user access token or platform agent key · Scope: weather:write

Request body

FieldTypeRequiredNotes
placesobject[]Yesup to 100 items
places[].placeIdstringNomatches ^[A-Za-z0-9:_.-]{1,64}$
places[].namestringYes1–100 characters; trimmed
places[].regionstringNoup to 100 characters; trimmed
places[].countrystringNoup to 100 characters; trimmed
places[].latnumberYes-90–90
places[].lonnumberYes-180–180
places[].timeZonestringYes1–64 characters
units"metric" | "imperial"No

Response 200

{
  places: {
    placeId: string
    name: string
    region?: string
    country?: string
    lat: number
    lon: number
    timeZone: string
  }[]
  units: "metric" | "imperial"
  updatedAt?: number
}

Errors

StatusMessage
403Saved places belong to people, not keys.
403Change your places in the Weather app.