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.
POST /api/v1/readings
Section titled “POST /api/v1/readings”Auth: Required (Bearer JWT)
Required vs. optional
Section titled “Required vs. optional”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.
Request body
Section titled “Request body”{ "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" } ]}Fields
Section titled “Fields”| Field | Type | Required | Constraints / notes |
|---|---|---|---|
timestamp | string (ISO 8601) | Yes | UTC recommended |
indoor_temp | float | Yes | 30.0–120.0 °F |
hvac_state | string | Yes | "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_humidity | float | No | Percent (0–100) |
outdoor_temp | float | No | Fahrenheit |
target_temp | float | No | Current thermostat setpoint |
fan_mode | string | No | Fan-speed label, e.g. "auto", "low", "high". Stored as sent. |
power_watts | float | No | Current power draw. Send only if the meter measures this specific unit — a shared/whole-home meter can mislead the model. |
hvac_action | string | No | The 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_mode | string | No | The mode your integration last commanded ("COOL"/"HEAT"/"OFF"). Send when available; improves accuracy. |
commanded_fan_mode | string | No | The fan label your integration last commanded. |
commanded_setpoint | float | No | The setpoint (°F) your integration last commanded. |
appliance_id | string (UUID) | Conditional | Tags 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. |
Example (minimum viable reading)
Section titled “Example (minimum viable reading)”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" } ] }'Response (201)
Section titled “Response (201)”{ "accepted": 1}The accepted count reflects how many readings were stored.
Errors
Section titled “Errors”| Status | Detail | Cause |
|---|---|---|
| 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) |
Rate limit
Section titled “Rate limit”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.
How readings are used
Section titled “How readings are used”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.