wxlistener can POST weather data to any HTTP endpoint in a structured JSON format. This is useful for custom APIs, cloud services, webhooks, or data collection endpoints.
Add an [http] section to your wxlistener.toml:
[http]
url = "https://example.com/api/weather" # Required
timeout = 10 # Optional, default: 10 seconds
authorization = "Bearer your-token-here" # OptionalYou can also configure HTTP output using environment variables:
export WXLISTENER_HTTP_URL="https://example.com/api/weather"
export WXLISTENER_HTTP_AUTH="Bearer your-token-here" # OptionalEnvironment variables are used when:
- No config file is specified, or
- The config file doesn't have an
[http]section
| Option | Required | Default | Description |
|---|---|---|---|
url |
Yes | - | The HTTP endpoint URL to POST data to |
timeout |
No | 10 | Request timeout in seconds |
authorization |
No | - | Value for the Authorization header |
Data is POSTed as JSON with the following structure:
{
"weather_measurement": {
"reading_date_time": "1970-01-01T00:00:00.000Z",
"barometer_abs": float,
"barometer_rel": float,
"day_max_wind": float,
"dewpoint": float,
"gust_speed": float,
"heatindex": float,
"humidity": integer,
"light": float,
"rain_day": float,
"rain_event": float,
"rain_rate": float,
"temperature": float,
"uv": integer,
"uvi": integer,
"wind_dir": integer,
"wind_speed": float,
"windchill": float,
"soil": [
{
"channel": integer,
"moisture": float,
"battery": float
}
],
"temp_probes": [
{
"channel": integer,
"temperature": float,
"battery": float
}
]
}
}Important: Only raw numeric values are sent—no units of measure are included.
| HTTP Output Field | Weather Station Field | Type | Description |
|---|---|---|---|
reading_date_time |
(timestamp) | string | ISO 8601 timestamp with milliseconds |
barometer_abs |
absbarometer |
float | Absolute barometric pressure (hPa) |
barometer_rel |
relbarometer |
float | Relative barometric pressure (hPa) |
day_max_wind |
day_max_wind |
float | Maximum wind speed today (m/s) |
dewpoint |
dewpoint |
float | Dew point (°C) |
gust_speed |
gust_speed |
float | Current wind gust speed (m/s) |
heatindex |
heatindex |
float | Heat index (°C) |
humidity |
outhumid |
integer | Outdoor humidity (%) |
light |
light |
float | Light intensity (lux) |
windchill |
windchill |
float | Wind chill (°C) |
rain_day |
rain_day |
float | Rain today (mm) |
rain_event |
rain_event |
float | Rain since event started (mm) |
rain_rate |
rain_rate |
float | Current rain rate (mm/h) |
temperature |
outtemp |
float | Outdoor temperature (°C) |
uv |
uv |
integer | UV radiation |
uvi |
uvi |
integer | UV index |
wind_dir |
wind_dir |
integer | Wind direction (degrees) |
wind_speed |
wind_speed |
float | Current wind speed (m/s) |
soil[].channel |
(1–8) | integer | WH51 soil moisture channel |
soil[].moisture |
soil_moisture_chN |
float | WH51 soil moisture (%) |
soil[].battery |
soil_battery_chN |
float | WH51 battery voltage (V) |
temp_probes[].channel |
(1–8) | integer | Multi-channel temp probe channel |
temp_probes[].temperature |
tf_temp_chN |
float | WN34/WN34S temperature (°C, same as temperature) |
temp_probes[].battery |
tf_battery_chN |
float | WN34/WN34S battery voltage (V) |
Note: Fields are only included if the weather station provides them. Missing sensor data results in omitted fields (not null values). The soil and temp_probes arrays are omitted when empty. WH51 is moisture-only; WN34/WN34S probes use ITEM_TF_USR* and appear under temp_probes.
{
"weather_measurement": {
"reading_date_time": "2025-12-10T15:30:45.123Z",
"barometer_abs": 1013.25,
"barometer_rel": 1010.0,
"day_max_wind": 12.5,
"dewpoint": 15.2,
"gust_speed": 8.2,
"heatindex": 24.0,
"humidity": 65,
"light": 50000.0,
"windchill": 21.5,
"rain_day": 2.5,
"rain_event": 1.0,
"rain_rate": 0.5,
"temperature": 22.5,
"uv": 5,
"uvi": 3,
"wind_dir": 180,
"wind_speed": 5.5
}
}The authorization config option sets the Authorization HTTP header. Common formats:
Bearer Token
[http]
url = "https://api.example.com/weather"
authorization = "Bearer eyJhbGciOiJIUzI1NiIs..."API Key
[http]
url = "https://api.example.com/weather"
authorization = "ApiKey your-api-key-here"Basic Auth
[http]
url = "https://api.example.com/weather"
authorization = "Basic dXNlcm5hbWU6cGFzc3dvcmQ="wxlistener will exit with an error if HTTP publishing fails. Common error scenarios:
| Error | Cause | Solution |
|---|---|---|
| "Invalid HTTP endpoint URL" | Malformed URL | Check URL format (must include scheme) |
| "Failed to send HTTP request" | Network/connection error | Verify endpoint is reachable |
| "HTTP request failed with status XXX" | Server returned error | Check server logs, authentication |
| "request timed out" | Endpoint too slow | Increase timeout value |
const express = require("express");
const app = express();
app.use(express.json());
app.post("/api/weather", (req, res) => {
const { weather_measurement } = req.body;
console.log("Received weather data:", weather_measurement);
console.log("Temperature:", weather_measurement.temperature);
console.log("Humidity:", weather_measurement.humidity);
console.log("Timestamp:", weather_measurement.reading_date_time);
// Store in database, forward to another service, etc.
res.status(200).json({ status: "ok" });
});
app.listen(3000, () => {
console.log("Weather API listening on port 3000");
});from flask import Flask, request, jsonify
from datetime import datetime
app = Flask(__name__)
@app.route('/api/weather', methods=['POST'])
def receive_weather():
data = request.get_json()
measurement = data.get('weather_measurement', {})
print(f"Received weather data at {measurement.get('reading_date_time')}")
print(f"Temperature: {measurement.get('temperature')}°C")
print(f"Humidity: {measurement.get('humidity')}%")
# Store in database, process, etc.
return jsonify({'status': 'ok'}), 200
if __name__ == '__main__':
app.run(host='0.0.0.0', port=3000)wxlistener works with webhook services like:
- Zapier: Create a Zap with "Webhooks by Zapier" trigger
- IFTTT: Use the Webhooks service as a trigger
- n8n: Use the Webhook node to receive data
- Make (Integromat): Use the Webhooks module
Configure the webhook URL as your [http].url and add any required authentication.
Cause: Missing or invalid URL.
Solution: Ensure url is set in config or WXLISTENER_HTTP_URL environment variable.
Cause: Network connectivity issue or endpoint not reachable.
Solutions:
- Verify the endpoint URL is correct
- Check network connectivity:
curl -v <your-url> - Ensure firewall allows outbound connections
- Check if the endpoint requires VPN access
Cause: Authentication required or invalid credentials.
Solution: Verify authorization header value matches what the endpoint expects.
Cause: Server rejected the request.
Solutions:
- Check endpoint server logs for details
- Verify the endpoint accepts POST requests with JSON body
- Ensure Content-Type: application/json is accepted
Cause: Endpoint is slow or unresponsive.
Solution: Increase timeout in config:
[http]
url = "https://example.com/api/weather"
timeout = 30 # Increase to 30 secondsUse curl to test your endpoint with sample data:
curl -X POST https://your-endpoint.com/api/weather \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your-token" \
-d '{
"weather_measurement": {
"reading_date_time": "2025-12-10T15:30:45.123Z",
"temperature": 22.5,
"humidity": 65,
"wind_speed": 5.5
}
}'