Pro Weather.
Getting started

Push readings as JSON

A documented JSON format for feeding a Pro Weather site from a script, a Raspberry Pi or a home-built sensor with no weather-station firmware.

For a script, a Raspberry Pi or a home-built sensor, POST JSON to your upload URL with a JSON content type:

curl -X POST https://pro-weather.com/api/ingest/YOUR-INGEST-TOKEN \
  -H 'Content-Type: application/json' \
  -d '{
    "units": { "temperature": "C", "windspeed": "kph", "rainfall": "mm", "pressure": "hPa" },
    "lastupdated": "2026-08-07T14:30:00Z",
    "temperature": { "outdoor": 18.4, "indoor": 21.0 },
    "humidity":    { "outdoor": 67 },
    "wind":        { "speed": 11.2, "direction": 213, "gust10m": 24.0 },
    "rain":        { "counter": 812.4, "rate": 0.0 },
    "pressure":    { "sealevel": 1013.2, "absolute": 998.4 },
    "solar":       { "irradiation": 286, "uvi": 2 }
  }'

An accepted reading returns success. A payload with no usable reading returns HTTP 400.

Declare your units

Say what units you send and we convert. A value whose unit is missing or not recognised is dropped, never guessed: a temperature read in the wrong scale is worse than none. The rest of the payload still lands.

GroupAccepted values
temperatureC, F
windspeedmph, ms, kph, knots
rainfallmm, cm, in
pressurehPa, mb, kPa, inHg
lightningkm, mi
laserdistmm, cm, in
soilmoisture% (the default; any other unit drops the readings)

Fields

Everything is optional, but send at least one of outdoor temperature, humidity, wind speed, sea-level pressure, rain, solar radiation or PM2.5. A field you leave out means "no sensor", not zero.

FieldContents
lastupdatedISO 8601 or unix seconds. Anything unreadable falls back to arrival time.
temperatureoutdoor, indoor, dewpoint
humidityoutdoor, indoor (percent)
windspeed, gust10m, direction (degrees)
raincounter (a running total, see below), year, rate (per hour)
pressuresealevel, absolute
solarirradiation (W/m²), uvi
co2co2, co2_24h, pm2p5, pm2p5avg24h, pm10, pm10avg24h, temperature, humidity
lightningdistance, strikes (a running total), time

rain.counter and lightning.strikes are running totals, not today's figure. Today's rain and strike count are worked out from the difference between uploads and reset at your station's local midnight, so the first upload only sets the starting point. A counter that resets itself at midnight works too.

Multi-channel sensors are arrays, each entry with its own index (1-16):

FieldEntry shape
extratemp{ index, temperature, humidity }
usertemp{ index, temperature }
soiltemp{ index, temperature }
soilmoisture{ index, value } (percent)
leafwetness{ index, value }
airquality{ index, pm2p5, pm2p5avg24h, pm10, pm10avg24h } (PM10 on channel 1 only)
laserdist{ index, range, depth } (snow depth sensors, channels 1-4)

Good to know

  • Dew point, feels-like and cloud base are calculated for you. A dew point you send wins over the calculated one.
  • A reading outside a plausible range is dropped on its own, so one stuck channel cannot spoil the whole upload.
  • Once a minute is plenty. More than about one upload every 4 seconds is rate-limited (HTTP 429). The archive keeps one reading about every 4 minutes however often you post.
  • The format matches the JSON station format documented for CumulusMX, so a sender that already emits it can point here unchanged.

On this page