HeatingControl External API (1.0.22 (Draft))

Download OpenAPI specification:

Last updated: 2026-03-25

Overview

The HeatingControl External API allows external developers to integrate with the HeatingControl ecosystem. Through this API you can list homes, manage devices, read device state, update settings, and send commands.

Important: API Status and Compatibility

This API is currently in DRAFT status. While in draft, breaking changes may still occur as the API design is being finalized. The draft period will end with the first official release.

After the first official release, this API may be extended at any time with non-breaking changes. Your client code must be designed to handle these gracefully and not break when encountering unknown data.

Non-breaking changes include but are not limited to:

  • New fields added to response objects
  • New values for existing string/enum fields
  • New optional query parameters or request body fields
  • New endpoints
  • Relaxed validation on existing fields (e.g. accepting a wider range of values)

Breaking changes (removed fields, changed types, altered semantics) will only be introduced in a new API version (e.g. /v2).

As a best practice, ignore unknown fields rather than treating them as errors, and avoid strict schema validation that rejects unexpected properties.

Authentication

The API uses OAuth2 client credentials flow.

  1. Obtain a token — call POST /v1/oauth/token with your client_id and client_secret to receive an access token.
  2. Authorize requests — include the token in the Authorization header:
    Authorization: Bearer <access_token>
    
  3. Refresh tokens — tokens expire after a limited time. Call POST /v1/oauth/token again to obtain a new one before expiry.

Common workflows

A typical integration follows this sequence:

  1. Authenticate — obtain an access token.
  2. List homesGET /v1/homes to discover available homes.
  3. List devicesGET /v1/devices to enumerate devices (optionally filter by homeId).
  4. Read device stateGET /v1/devices/{deviceId}/state to read current state.
  5. Read device settingsGET /v1/devices/{deviceId}/settings to read current settings.
  6. Send commandsPOST /v1/devices/{deviceId}/commands/{key} to control a device.

Developer journey: controlling electric heaters

This walkthrough shows a complete integration flow for managing electric heaters — from obtaining a token to reading state and sending commands. Replace YOUR_CLIENT_ID, YOUR_CLIENT_SECRET, and the base URL with your actual values.

Step 1 — Obtain an access token

curl -X POST https://api.example.com/v1/oauth/token \
  -H "Content-Type: application/json" \
  -d '{
    "grant_type": "client_credentials",
    "client_id": "YOUR_CLIENT_ID",
    "client_secret": "YOUR_CLIENT_SECRET"
  }'

Response:

{
  "access_token": "eyJhbGciOiJSUzI1NiIs...",
  "refresh_token": "dGhpcyBpcyBhIHJlZnJl...",
  "expires_in": 3600,
  "token_type": "Bearer"
}

Save the access_token — you will include it in every subsequent request as Authorization: Bearer <access_token>.

Step 2 — List your devices

Discover the devices available in your account:

curl https://api.example.com/v1/devices \
  -H "Authorization: Bearer <access_token>"

Response:

{
  "items": [
    {
      "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "name": "Living Room Heater",
      "type": "heater",
      "subtype": "wifi_heater",
      "homeId": "h_abc123",
      "online": true,
      "fwVersion": "2.1.0",
      "hwVersion": "1.0",
      "gatewayId": null
    },
    {
      "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
      "name": "Bedroom Heater",
      "type": "heater",
      "subtype": "wifi_heater",
      "homeId": "h_abc123",
      "online": true,
      "fwVersion": "2.1.0",
      "hwVersion": "1.0",
      "gatewayId": null
    }
  ],
  "pagination": {
    "limit": 50,
    "cursor": null,
    "nextCursor": null,
    "hasMore": false
  }
}

Note the id of each device — you will use it in the next steps.

Step 3 — Read the state of a heater

Get the current state of the Living Room Heater, including temperature and power:

curl https://api.example.com/v1/devices/a1b2c3d4-e5f6-7890-abcd-ef1234567890/state \
  -H "Authorization: Bearer <access_token>"

Response:

{
  "type": "heater",
  "online": true,
  "mode": "auto",
  "indicators": ["active"],
  "currentTemperature": 20.5,
  "targetTemperature": 22.0,
  "temperatureUnits": "C",
  "power": 1500,
  "maxPower": 1500
}

Key fields:

  • mode — the current operating mode (e.g. auto, manual, off).
  • power — current power consumption in watts (0 when the heater is not actively heating).
  • maxPower — the rated maximum power of the heater in watts.

Step 4 — Change the mode and temperature

Switch the Living Room Heater to manual mode at 21 °C. First, check which commands are available:

curl https://api.example.com/v1/devices/a1b2c3d4-e5f6-7890-abcd-ef1234567890/commands \
  -H "Authorization: Bearer <access_token>"

Then execute the setMode command:

curl -X POST https://api.example.com/v1/devices/a1b2c3d4-e5f6-7890-abcd-ef1234567890/commands/setMode \
  -H "Authorization: Bearer <access_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "params": {
      "mode": "manual",
      "temperature": 21.0
    }
  }'

Response:

{
  "success": true,
  "message": "Command executed successfully"
}

Step 5 — Read the power of another heater

Check the Bedroom Heater to see if it is consuming power:

curl https://api.example.com/v1/devices/b2c3d4e5-f6a7-8901-bcde-f12345678901/state \
  -H "Authorization: Bearer <access_token>"

Response:

{
  "type": "heater",
  "online": true,
  "mode": "auto",
  "indicators": [],
  "currentTemperature": 22.1,
  "targetTemperature": 22.0,
  "temperatureUnits": "C",
  "power": 0,
  "maxPower": 2000
}

Here power is 0 because the room has already reached the target temperature and the heater is not actively heating. The maxPower of 2000 tells you this is a 2 kW heater.

Step 6 — Explore device settings

View the configurable settings for a device:

curl https://api.example.com/v1/devices/a1b2c3d4-e5f6-7890-abcd-ef1234567890/settings \
  -H "Authorization: Bearer <access_token>"

Response (abbreviated):

{
  "temperature_units": {
    "key": "temperature_units",
    "type": "enum",
    "label": "Temperature Units",
    "value": "C",
    "editable": true,
    "options": ["C", "F"]
  },
  "keyboard_locked": {
    "key": "keyboard_locked",
    "type": "boolean",
    "label": "Keyboard Lock",
    "value": false,
    "editable": true
  }
}

You can update a specific setting with a PATCH request:

curl -X PATCH https://api.example.com/v1/devices/a1b2c3d4-e5f6-7890-abcd-ef1234567890/settings/keyboard_locked \
  -H "Authorization: Bearer <access_token>" \
  -H "Content-Type: application/json" \
  -d '{ "value": true }'

Pagination

List endpoints support cursor-based pagination:

Parameter Description
limit Maximum number of items to return (default varies by endpoint).
cursor Opaque cursor returned in the previous response to fetch the next page.

When more results are available the response includes a cursor field. Pass it as a query parameter to retrieve the next page. When cursor is absent or null, you have reached the last page.

Error handling

All error responses follow a standard envelope:

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Human-readable description of the problem",
    "requestId": "abc-123",
    "details": {}
  }
}
Field Description
code Machine-readable error code (e.g. VALIDATION_ERROR, UNAUTHORIZED, NOT_FOUND).
message Human-readable explanation.
requestId Unique identifier for the request — useful when contacting support.
details Optional object with additional context (e.g. field-level validation errors).

Auth

Obtain and refresh access tokens

Obtain an access token

header Parameters
authorization
required
string
Request Body schema: application/json
required
grant_type
required
string
Enum: "client_credentials" "refresh_token"

OAuth2 grant type

client_id
string

Client identifier (required for client_credentials grant)

client_secret
string

Client secret (required for client_credentials grant)

refresh_token
string

Refresh token (required for refresh_token grant)

scope
string

Requested permission scopes

Responses

Request samples

Content type
application/json
{
  • "grant_type": "client_credentials",
  • "client_id": "string",
  • "client_secret": "string",
  • "refresh_token": "string",
  • "scope": "/user:W /devs/*:W"
}

Response samples

Content type
application/json
{
  • "access_token": "eyJhbGciOiJIUzI1NiIs...",
  • "refresh_token": "dGhpcyBpcyBhIHJlZnJl...",
  • "expires_in": 3600,
  • "token_type": "Bearer"
}

Homes

List and retrieve homes

List homes

Authorizations:
bearer
query Parameters
limit
number [ 1 .. 100 ]
Default: 20

Maximum number of homes to return

cursor
string

Cursor from a previous response to fetch the next page

Responses

Response samples

Content type
application/json
{
  • "items": [
    ],
  • "pagination": {
    }
}

Get a home

Authorizations:
bearer
path Parameters
homeId
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "aabbccdd-eeff-0011-2233-445500000000",
  • "name": "My Home",
  • "deviceCount": 3,
  • "location": {
    }
}

Devices

Manage devices, state, settings, and commands

List devices

Authorizations:
bearer
query Parameters
limit
number [ 1 .. 100 ]
Default: 20

Maximum number of devices to return

cursor
string

Cursor from a previous response to fetch the next page

homeId
string

Filter by home UUID

gatewayId
string

Filter devices by gateway UUID. Returns only devices connected through this gateway.

includeGateways
boolean
Default: false

Include gateway devices in the response

Responses

Response samples

Content type
application/json
{
  • "items": [
    ],
  • "pagination": {
    }
}

Get device info

Authorizations:
bearer
path Parameters
deviceId
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "0123456789abcdef01-0001-0000-0000-000000000000",
  • "name": "Living Room Heater",
  • "type": "heater",
  • "homeId": "aabbccdd-eeff-0011-2233-445500000000",
  • "online": true,
  • "subtype": "wifi_heater",
  • "fwVersion": "1.3",
  • "hwVersion": "3.0",
  • "gatewayId": null
}

Update device metadata

Authorizations:
bearer
path Parameters
deviceId
required
string <uuid>
Request Body schema: application/json
required
name
string

New display name for the device

Responses

Request samples

Content type
application/json
{
  • "name": "Bedroom Heater"
}

Response samples

Content type
application/json
{
  • "id": "0123456789abcdef01-0001-0000-0000-000000000000",
  • "name": "Living Room Heater",
  • "type": "heater",
  • "homeId": "aabbccdd-eeff-0011-2233-445500000000",
  • "online": true,
  • "subtype": "wifi_heater",
  • "fwVersion": "1.3",
  • "hwVersion": "3.0",
  • "gatewayId": null
}

Get device state

Authorizations:
bearer
path Parameters
deviceId
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "type": "heater",
  • "online": true,
  • "mode": "auto",
  • "indicators": [
    ],
  • "currentTemperature": 21.5,
  • "targetTemperature": 22,
  • "temperatureUnits": "C",
  • "chargeLevel": 75,
  • "power": 1500,
  • "maxPower": 2000
}

Get device settings

Authorizations:
bearer
path Parameters
deviceId
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "property1": {
    },
  • "property2": {
    }
}

Get a specific device setting

Authorizations:
bearer
path Parameters
deviceId
required
string <uuid>
key
required
string

Responses

Response samples

Content type
application/json
Example
{
  • "type": "boolean",
  • "key": "locked",
  • "label": "Keyboard Lock Enabled",
  • "value": false
}

Update a device setting

Authorizations:
bearer
path Parameters
deviceId
required
string <uuid>
key
required
string
Request Body schema: application/json
required
One of
value
required
boolean

New boolean value

Responses

Request samples

Content type
application/json
Example
{
  • "value": false
}

Response samples

Content type
application/json
Example
{
  • "type": "boolean",
  • "key": "locked",
  • "label": "Keyboard Lock Enabled",
  • "value": false
}

List available commands

Authorizations:
bearer
path Parameters
deviceId
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "property1": {
    },
  • "property2": {
    }
}

Execute a command

Authorizations:
bearer
path Parameters
deviceId
required
string <uuid>
key
required
string
Request Body schema: application/json
required
object

Command parameters. Use GET /devices/:id/commands to discover the expected parameter schema for each command.

Responses

Request samples

Content type
application/json
{
  • "params": {
    }
}

Response samples

Content type
application/json
{
  • "command": "setMode",
  • "state": "APPLIED",
  • "appliedAt": "2026-03-18T12:00:00.000Z"
}
Postman Collection OpenAPI Spec