API guide

How to use the Weather Guardian API

Weather Guardian gives you a simple API for reading weather station sensor data. You can pull the latest measurement, export historical readings, build dashboards, feed spreadsheets, and support research or reporting workflows.

The public Weather Guardian API is centred on sensor data and is documented in the Weather Guardian web app at /docs. In production, examples should use the Weather Guardian API base path:

https://weather-guardian.com/api
This guide covers the API-key authenticated sensor API: latest readings and historical exports.

Authentication

All sensor API requests require an API key. Send the key in the x-api-key request header:

x-api-key: YOUR_API_KEY

You can create a key from the Weather Guardian dashboard:

  1. Sign in to your Weather Guardian account.
  2. Open the API page from the dashboard navigation.
  3. In the API Key section, choose Generate key.
  4. Copy the key immediately. The plain text key is only shown once.

Regenerating a key revokes the previous one and creates a new one, so update any scripts, dashboards, scheduled jobs, or integrations that still use the old key. API keys are stored hashed server-side, but you should still treat the plain text key like a password: do not commit it to Git, do not paste it into public issue trackers, and use environment variables for production integrations.

Daily request limits

Each API-key request increments your daily API usage counter. The counter resets every day at 00:00 GMT. Default limits in the application are:

  • Free: 100 API requests per day and 30 days of history.
  • Standard: 10,000 API requests per day and unlimited history.
  • Educational: 100,000 API requests per day and unlimited history.
  • Enterprise: 100,000 API requests per day and unlimited history.

If your account reaches its daily API limit, the API returns HTTP 429:

{
  "error": "max api calls reached for today (err: 03)"
}

Sensor visibility and privacy

The API can read sensors in two cases:

  • Sensors owned by your account.
  • Public sensors owned by other users.

Private sensors can only be read by the owning account. If you try to read another user's private sensor, the API returns HTTP 403:

{
  "ok": false,
  "message": "unauthorised"
}

Location precision is privacy-aware too. Export responses include a geohash field. Owners receive the full stored location tile. Non-owners reading a public sensor receive a truncated location value, limited to the first five characters.

Use sensor IDs, not hub IDs

The sensor routes use the sensor device ID in the URL:

GET /api/sensors/{sensor}/latest
GET /api/sensors/{sensor}/export

Use the ID for the sensor, not the ID for its parent hub. If you call these routes with a hub ID or another non-sensor device, the API returns an error explaining that data can only be exported from sensors.

Endpoint 1: get the latest measurement

Use the latest endpoint when you only need the most recent reading from a sensor:

GET /api/sensors/{sensor}/latest

Example with curl:

curl -s \
  -H "Accept: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  "https://weather-guardian.com/api/sensors/SENSOR_ID/latest"

Example response:

{
  "observed_at": "2026-05-19T10:00:00+00:00",
  "received_at": "2026-05-19T10:00:01+00:00",
  "temperature_c": 18.4,
  "feels_like_c": 18.1,
  "dew_point_c": 11.2,
  "humidity_pct": 63,
  "pressure_hpa": 1011.2,
  "battery_pct": 0.91,
  "rssi_dbm": -67,
  "seq": 1204,
  "extras": null
}

If the sensor exists but has no measurements yet, this endpoint may return null.

Latest measurement fields

observed_at
When the sensor recorded the sample.
received_at
When Weather Guardian received the sample.
temperature_c
Temperature in degrees Celsius.
feels_like_c
Calculated feels-like temperature in degrees Celsius, when available.
dew_point_c
Calculated dew point in degrees Celsius, when available.
humidity_pct
Relative humidity percentage.
pressure_hpa
Pressure in hectopascals.
battery_pct
Battery value as stored by the device.
rssi_dbm
Signal strength in dBm, when available.
seq
Device sequence number, when available.
extras
Additional device-specific metrics.

Endpoint 2: export sensor history

Use the export endpoint when you need measurements across a date range:

GET /api/sensors/{sensor}/export

Required query parameters:

  • from: start of the range. Use ISO-8601 datetime strings such as 2026-05-01T00:00:00Z.
  • agg_type: aggregation type. Must be one of raw, hour, or day.

Optional query parameter:

  • to: end of the range. If omitted, it defaults to now.

Example hourly export request:

curl -s \
  -H "Accept: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  "https://weather-guardian.com/api/sensors/SENSOR_ID/export?from=2026-05-01T00:00:00Z&to=2026-05-07T23:59:59Z&agg_type=hour"

Date handling

Dates are processed in UTC. The code accepts normal date strings that Carbon can parse, including ISO-8601 strings. The generated API docs also describe Unix timestamps in seconds or milliseconds, but the current controller validates from and to as strings before parsing, so ISO-8601 strings are the safest format for integrations.

For export requests, the server expands the requested dates to full days:

  • from is moved to the start of its day.
  • to is moved to the end of its day.
  • If to is omitted, it uses the current time.

On accounts with a limited history window, the API clamps from forward to the earliest date allowed by the subscription. For example, the default free tier has a 30-day history window.

Choosing an aggregation type

Pick an aggregation type based on what your integration is trying to do. The goal is to request enough detail for your use case without moving more data than necessary.

  • raw: use this when you need individual measurements. Raw exports are ordered oldest to newest and are limited to 10,000 rows per request.
  • hour: use this for charts covering several days or weeks. It keeps payloads smaller while preserving useful detail.
  • day: use this for long-term reports, comparisons, and low-volume integrations.

Export response examples

Raw export response

{
  "ok": true,
  "geohash": "gcpvj0d12345",
  "data": [
    {
      "observed_at": "2026-05-01T09:00:00.000000Z",
      "pressure_hpa": "1013.20",
      "temperature_c": "19.80",
      "humidity_pct": "62.10",
      "battery_pct": "0.91",
      "feels_like_c": "19.60",
      "dew_point_c": "12.30"
    }
  ]
}

Raw data includes observed_at, pressure_hpa, temperature_c, humidity_pct, battery_pct, feels_like_c, and dew_point_c when present.

Hourly export response

{
  "ok": true,
  "geohash": "gcpvj0d12345",
  "data": {
    "2026-05-01": {
      "hours": {
        "9": {
          "temperature": { "avg": 19.8, "min": 18.9, "max": 20.4 },
          "humidity": { "avg": 62.1, "min": 59.2, "max": 64.0 },
          "pressure": { "avg": 1013.2, "min": 1012.8, "max": 1013.5 },
          "dew_point": { "avg": 12.3, "min": 11.8, "max": 12.9 },
          "feels_like": { "avg": 19.6, "min": 18.7, "max": 20.1 }
        }
      }
    }
  }
}

Hourly data is grouped by date, then by hour number from 0 to 23. Each metric contains avg, min, and max values.

Daily export response

{
  "ok": true,
  "geohash": "gcpvj0d12345",
  "data": [
    {
      "2026-05-01": {
        "temperature": { "avg": 18.7, "min": 16.9, "max": 20.8 },
        "humidity": { "avg": 63.2, "min": 54.0, "max": 71.4 },
        "pressure": { "avg": 1014.1, "min": 1009.8, "max": 1017.2 },
        "dew_point": { "avg": 11.9, "min": 10.4, "max": 13.2 },
        "feels_like": { "avg": 18.4, "min": 16.2, "max": 20.1 }
      }
    }
  ]
}

Daily data is returned as an array. Each item is keyed by date in YYYY-MM-DD format and contains avg, min, and max values for each available metric.

JavaScript and Python examples

JavaScript: read the latest measurement

const apiKey = process.env.WEATHER_GUARDIAN_API_KEY;
const sensorId = "SENSOR_ID";

const response = await fetch(
  `https://weather-guardian.com/api/sensors/${sensorId}/latest`,
  {
    headers: {
      Accept: "application/json",
      "x-api-key": apiKey,
    },
  }
);

if (!response.ok) {
  throw new Error(`Weather Guardian API error: ${response.status}`);
}

const latest = await response.json();
console.log(latest.temperature_c, latest.humidity_pct, latest.pressure_hpa);

Python: export daily summaries for the last seven days

import os
import requests
from datetime import datetime, timedelta, timezone

api_key = os.environ["WEATHER_GUARDIAN_API_KEY"]
sensor_id = "SENSOR_ID"

to_dt = datetime.now(timezone.utc)
from_dt = to_dt - timedelta(days=7)

response = requests.get(
    f"https://weather-guardian.com/api/sensors/{sensor_id}/export",
    headers={
        "Accept": "application/json",
        "x-api-key": api_key,
    },
    params={
        "from": from_dt.isoformat(),
        "to": to_dt.isoformat(),
        "agg_type": "day",
    },
    timeout=30,
)

response.raise_for_status()
payload = response.json()
print(payload["data"])

Common API errors

Build your integration to handle authentication, permission, validation, and usage-limit responses explicitly.

Missing API key

HTTP 401
{
  "error": "missing x-api-key header"
}

Invalid API key

HTTP 401
{
  "error": "invalid api key (err: 00)"
}

Daily limit reached

HTTP 429
{
  "error": "max api calls reached for today (err: 03)"
}

Private sensor or unauthorised access

HTTP 403
{
  "ok": false,
  "message": "unauthorised"
}

Invalid export parameters

HTTP 422
{
  "ok": false,
  "message": "validation failed",
  "errors": {
    "agg_type": [
      "The selected agg type is invalid."
    ]
  }
}

Unparseable dates or inverted ranges

HTTP 422
{
  "ok": false,
  "message": "unable to parse from date"
}

HTTP 403
{
  "ok": false,
  "message": "unable to parse to date"
}

HTTP 403
{
  "ok": false,
  "message": "to date must be after from date"
}

Best practices

  • Use /latest for dashboard tiles or status checks that only need the newest reading.
  • Use agg_type=hour for most charts. It is usually detailed enough and more efficient than raw exports.
  • Use agg_type=day for long date ranges, reports, and trend comparisons.
  • Use agg_type=raw only when individual observations matter.
  • Cache responses where possible so you do not burn through your daily request limit.
  • Request the smallest date range you need.
  • Store API keys in environment variables.
  • Handle 401, 403, 422, and 429 responses explicitly in your integration.

Quick reference

Base path
/api
Authentication header
x-api-key: YOUR_API_KEY
Latest reading
GET /api/sensors/{sensor}/latest
Historical export
GET /api/sensors/{sensor}/export?from=2026-05-01T00:00:00Z&to=2026-05-07T23:59:59Z&agg_type=hour
Aggregation options
raw, hour, day
Live docs
/docs
Need a broader product view? Visit weather-guardian.com or explore the Weather Guardian web platform.

More Weather Guardian guides

Browse the blog for practical guides about dashboards, weather alerts, sensor history, and API workflows.