XGuarden Home API

Read the state of connected devices, send commands, run scenes and build automations for a home through one JSON REST interface.

All systems operational

Authentication

Authenticate with a secret key sent as a bearer token. Keys are scoped to a single home and can be limited to read-only access. Never embed a key in a mobile app or a public repository.

Request

curl https://xguarden.tech/v2/homes/home_5aT2k/devices \
  -H "Authorization: Bearer xg_live_••••••••••••••••" \
  -H "Accept: application/json"

Response when the key is missing or invalid (401)

{
  "error": {
    "type": "authentication_error",
    "code": "invalid_api_key",
    "message": "The API key provided is missing or invalid.",
    "request_id": "req_8f2c1a9d4e7b"
  }
}
Keys prefixed xg_test_ connect to simulated devices, so you can try commands without touching a real home.

Device object

A device exposes one or more capabilities. state is the last reported value and desired holds a command that has not been confirmed by the device yet.

{
  "id": "dev_9Xq2LmT4",
  "object": "device",
  "home_id": "home_5aT2k",
  "room_id": "room_living",
  "name": "Living room thermostat",
  "type": "thermostat",
  "manufacturer": "Aurora",
  "model": "T-210",
  "firmware": "3.8.2",
  "protocol": "zigbee",
  "online": true,
  "battery": null,
  "capabilities": ["temperature.target", "temperature.current", "mode"],
  "state": {
    "temperature.current": 21.4,
    "temperature.target": 22.0,
    "mode": "heat"
  },
  "desired": {},
  "last_seen_at": "2026-10-03T19:58:41Z"
}

Send a command

Commands are asynchronous. The API returns 202 as soon as the hub accepts the command, and the device state changes once the device confirms it. Use an Idempotency-Key header to make retries safe.

curl -X POST https://xguarden.tech/v2/devices/dev_9Xq2LmT4/commands \
  -H "Authorization: Bearer xg_live_••••••••••••••••" \
  -H "Idempotency-Key: 7c1d2a4e-5b0f-4e6e-9a3d-0f8e2b6c1a77" \
  -H "Content-Type: application/json" \
  -d '{"capability":"temperature.target","value":22.5}'

Response (202)

{
  "id": "cmd_4Hn8wQ1z",
  "object": "command",
  "device_id": "dev_9Xq2LmT4",
  "capability": "temperature.target",
  "value": 22.5,
  "status": "pending",
  "created_at": "2026-10-03T20:01:12Z",
  "expires_at": "2026-10-03T20:02:12Z"
}

Device endpoints

MethodPathDescription
GET/v2/homes/{id}/devicesList devices. Filter by room_id, type or online.
GET/v2/devices/{id}Retrieve a device and its current state.
PUT/v2/devices/{id}Rename a device or move it to another room.
DELETE/v2/devices/{id}Remove a device from the home.
POST/v2/devices/{id}/commandsSend a command to a device.
GET/v2/commands/{id}Check whether a command was confirmed, failed or expired.
GET/v2/devices/{id}/historyState changes over time. Pass from, to and capability.
GET/v2/healthService health. Does not require authentication.

Capabilities

CapabilityTypeDescription
powerbooleanTurn a plug, light or appliance on or off.
brightnessinteger, 0 to 100Light level in percent.
color.temperatureinteger, 2000 to 6500White tone in kelvin.
temperature.targetnumberTarget temperature in °C.
locklocked, unlockedDoor lock state. Unlocking requires a key with the locks:write scope.
positioninteger, 0 to 100Blinds and garage doors, 0 is closed.
motionbooleanMotion detected. Read-only.
contactopen, closedDoor and window sensors. Read-only.

Rooms

Rooms group devices so a command or scene can target everything in one place.

MethodPathDescription
GET/v2/homes/{id}/roomsList rooms with device counts.
POST/v2/homes/{id}/roomsCreate a room.
POST/v2/rooms/{id}/commandsSend one command to every compatible device in the room.

Scenes

A scene is a saved set of commands that runs together.

POST /v2/homes/home_5aT2k/scenes
 
{
  "name": "Evening",
  "actions": [
    { "room_id": "room_living", "capability": "brightness", "value": 35 },
    { "device_id": "dev_9Xq2LmT4", "capability": "temperature.target", "value": 21.5 },
    { "device_id": "dev_Lk3p7WcA", "capability": "position", "value": 0 }
  ]
}

Run it with POST /v2/scenes/{id}/activate. The response lists the command created for each action.

Automations

Automations run a scene or commands when a trigger fires and every condition is true. Supported triggers are schedule, sunrise, sunset, device_state and presence.

{
  "id": "aut_2Wn5Rj8c",
  "name": "Close blinds at sunset",
  "enabled": true,
  "trigger": { "type": "sunset", "offset_minutes": -15 },
  "conditions": [
    { "type": "weekday", "in": ["mon", "tue", "wed", "thu", "fri"] }
  ],
  "actions": [
    { "room_id": "room_living", "capability": "position", "value": 0 }
  ],
  "last_run_at": "2026-10-03T17:41:00Z"
}

Energy

Devices with power metering report consumption in watt-hours. Totals are available per home, room or device and can be grouped by hour, day or month.

GET /v2/homes/home_5aT2k/energy?from=2026-10-01&to=2026-10-03&group_by=day
 
{
  "unit": "Wh",
  "data": [
    { "date": "2026-10-01", "total": 11840, "by_room": { "room_living": 4210, "room_kitchen": 5120 } },
    { "date": "2026-10-02", "total": 12310, "by_room": { "room_living": 4390, "room_kitchen": 5370 } },
    { "date": "2026-10-03", "total": 10975, "by_room": { "room_living": 3980, "room_kitchen": 4760 } }
  ]
}

Webhooks

Register an HTTPS endpoint to receive events. Each request is signed with an HMAC-SHA256 of the raw body using your webhook secret, sent in the X-XGuarden-Signature header. Respond with any 2xx status within 10 seconds. Failed deliveries are retried up to 8 times over 24 hours.

EventSent when
device.state_changedA device reported a new state.
device.offlineA device has not reported for more than 10 minutes.
device.battery_lowA battery-powered device dropped below 15 percent.
command.failedA command expired or was rejected by the device.
scene.activatedA scene started, manually or from an automation.
hub.offlineA hub lost its connection to the cloud.
POST /hooks/xguarden HTTP/1.1
Content-Type: application/json
X-XGuarden-Event: device.state_changed
X-XGuarden-Signature: sha256=5f3a1c0e9b7d...
 
{
  "id": "evt_0d7a2f9e41",
  "type": "device.state_changed",
  "created_at": "2026-10-03T20:01:14Z",
  "data": {
    "device_id": "dev_9Xq2LmT4",
    "capability": "temperature.target",
    "previous": 22.0,
    "value": 22.5
  }
}

Event stream

For dashboards that need updates without running a server, open a Server-Sent Events connection. The stream sends a heartbeat comment every 25 seconds and resumes from the last event ID if you reconnect with the Last-Event-ID header.

curl -N https://xguarden.tech/v2/homes/home_5aT2k/events \
  -H "Authorization: Bearer xg_live_••••••••••••••••" \
  -H "Accept: text/event-stream"

Errors

The API uses standard HTTP status codes. Every error body contains a machine-readable code and a request_id to include when contacting support.

StatusMeaning
400The request is malformed, or the value is outside the range the capability accepts.
401The API key is missing, invalid or revoked.
403The key is read-only or lacks the required scope, such as locks:write.
404The home, device or room does not exist.
409The device is offline, or another command for the same capability is still pending.
422The device does not support this capability.
429Too many requests. Retry after the interval in the Retry-After header.
500, 503A temporary problem on our side. Retry with exponential backoff.
504The hub did not answer in time. The command was not delivered.

Rate limits

Each key can make 100 requests per second, with bursts up to 300. Each device accepts at most 10 commands per minute to protect battery-powered hardware. Every response includes X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset headers.

Changelog

2.4 — September 2026

Added the hub.offline event and per-room energy totals.

2.3 — June 2026

Added the Server-Sent Events stream and sunrise and sunset triggers for automations.

2.2 — March 2026

Added scopes for keys, including read-only access and locks:write.