Skip to content

Readings

The readings endpoint accepts HVAC sensor data from your thermostat or Home Assistant integration. Push a reading every 5 minutes (or batch several) so Hungry Machines can learn how your home responds and produce accurate schedules.

Auth: Required (Bearer JWT)

Only three fields are required on each reading: timestamp, indoor_temp, and hvac_state. Everything else is optional — but the more you send, the more accurate your schedules become. Send whatever your device exposes; there’s no penalty for omitting a field you don’t have.

{
"readings": [
{
"timestamp": "2025-11-18T14:30:00+00:00",
"indoor_temp": 72.5,
"hvac_state": "COOL",
"indoor_humidity": 45.0,
"outdoor_temp": 85.0,
"target_temp": 72.0,
"fan_mode": "auto",
"power_watts": 298.0,
"hvac_action": "cooling",
"commanded_hvac_mode": "COOL",
"commanded_fan_mode": "low",
"commanded_setpoint": 71.0,
"appliance_id": "11111111-1111-1111-1111-111111111111"
}
]
}
FieldTypeRequiredConstraints / notes
timestampstring (ISO 8601)YesUTC recommended
indoor_tempfloatYes30.0–120.0 °F
hvac_statestringYes"HEAT", "COOL", "ECO", "DRY", "OFF", or "FAN". Common aliases ("cooling", "eco_cool", "dehumidify", "fan_only", "heat_cool", "auto", "idle") are normalized server-side — pass whatever your thermostat reports. "ECO" and "DRY" are tracked separately from "COOL".
indoor_humidityfloatNoPercent (0–100)
outdoor_tempfloatNoFahrenheit
target_tempfloatNoCurrent thermostat setpoint
fan_modestringNoFan-speed label, e.g. "auto", "low", "high". Stored as sent.
power_wattsfloatNoCurrent power draw. Send only if the meter measures this specific unit — a shared/whole-home meter can mislead the model.
hvac_actionstringNoThe climate entity’s hvac_action attribute ("cooling", "heating", "idle", "off", …) — whether the unit is actively conditioning right now, as opposed to its standing mode. Send when available; improves accuracy.
commanded_hvac_modestringNoThe mode your integration last commanded ("COOL"/"HEAT"/"OFF"). Send when available; improves accuracy.
commanded_fan_modestringNoThe fan label your integration last commanded.
commanded_setpointfloatNoThe setpoint (°F) your integration last commanded.
appliance_idstring (UUID)ConditionalTags the reading with a specific HVAC (or dehumidifier) unit. Required once the account has more than one reading-producing appliance; optional for a single-HVAC account. Must reference an appliance the caller owns.
Terminal window
curl -X POST https://api.hungrymachines.io/api/v1/readings \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"readings": [
{
"timestamp": "2025-11-18T14:30:00+00:00",
"indoor_temp": 72.5,
"hvac_state": "COOL"
}
]
}'
{
"accepted": 1
}

The accepted count reflects how many readings were stored.

StatusDetailCause
400"indoor_temp must be between 30 and 120"A field failed validation
400"appliance_id <uuid> is not a hvac appliance owned by this user"appliance_id doesn’t reference an HVAC (or dehumidifier) unit the caller owns
401"Not authenticated"Missing or invalid token
429"Rate limit exceeded: ..."Over the daily reading ceiling (see below)

The daily reading ceiling is a runaway-loop safeguard, not a normal-use limit. It scales with how many appliances the account runs — at one reading every 5 minutes, a single HVAC generates ~288 readings/day, comfortably under the cap. It only trips on stuck loops or very large catch-up batches. If you legitimately run several appliances, tag each reading with its appliance_id — the ceiling scales with your active appliance count.

Hungry Machines uses your readings to learn how your home heats and cools and to generate the optimized schedules you pull from /api/v1/schedule. It needs a few days of continuous readings before it switches from safe defaults to optimized schedules — keep pushing consistently and the switch happens on its own. Gaps slow it down, because there’s less to learn from.