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
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:
- Sign in to your Weather Guardian account.
- Open the API page from the dashboard navigation.
- In the API Key section, choose Generate key.
- 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 as2026-05-01T00:00:00Z.agg_type: aggregation type. Must be one ofraw,hour, orday.
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:
fromis moved to the start of its day.tois moved to the end of its day.- If
tois 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
/latestfor dashboard tiles or status checks that only need the newest reading. - Use
agg_type=hourfor most charts. It is usually detailed enough and more efficient than raw exports. - Use
agg_type=dayfor long date ranges, reports, and trend comparisons. - Use
agg_type=rawonly 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