# Xenia Coffee Machine REST API Reference

Device: Xenia Coffee (ESP32-based controller)
IP: 10.0.50.128 (VLAN 50/IoT)
Firmware: ESP FW 3.9
Serial: 313253795029
Web UI: `http://10.0.50.128/` (Bootstrap, German)

## API Discovery

The JS bundle reveals all endpoints:
```bash
curl -s --compressed http://10.0.50.128/js/index_combined.js | grep -oP '/api/v2/[a-z_]+'
```

## Endpoints

### GET /api/v2/overview
Returns live machine telemetry. Poll this for sensor data.

```json
{
  "MA_EXTRACTIONS": 1877,
  "MA_OPERATING_HOURS": 39140,
  "MA_STATUS": 0,              // 0=Off, 1=On
  "MA_CLOCK": 1318439,
  "MA_CUR_PWR": 0,             // Watts (current draw)
  "MA_MAX_PWR": 10,            // Max ampere setting
  "MA_ENERGY_TOTAL_KWH": 13.25,
  "BG_SENS_TEMP_A": 32.7,     // Brew group temp °C
  "BG_LEVEL_PW_CONTROL": 0,
  "PU_SENS_PRESS": 0,         // Pump pressure
  "PU_LEVEL_PW_CONTROL": 0,
  "PU_SET_LEVEL_PW_CONTROL": 0,
  "SB_SENS_PRESS": 0,         // Steam boiler pressure
  "BB_SENS_TEMP_A": 32.2,     // Brew boiler temp °C
  "BB_LEVEL_PW_CONTROL": 0,
  "SB_STATUS": 1,              // Steam boiler status
  "MA_LAST_EXTRACTION_ML": ""
}
```

### GET /api/v2/machine
Machine configuration and identity.

```json
{
  "MA_TYPE": 0,
  "MA_FIX_WATER_SUPPLY": 0,
  "MA_HEATUP_FLUSH_EN": 0,
  "MA_SET_TIMER_ECO_MA": 0,
  "MA_SET_TIMER_POWERDOWN": 0,
  "MA_MAX_AMPERE": 10,
  "MA_ENERGY_TOTAL_KWH": 13.25,
  "FW_VERSION_MAJOR": 0,
  "FW_VERSION_MINOR": 0,
  "ESP_FW_MAJOR": 3,
  "ESP_FW_MINOR": 9,
  "MA_SN": "313253795029"
}
```

### POST /api/v2/machine/control
Power control endpoint. POST with JSON body:
- `{"action": 5}` — Turn ON
- `{"action": 3}` — Turn OFF
- `{"action": 4}` — ECO mode

HA `rest_command.xenia_machine_control` calls this endpoint.

### Other Endpoints
- `GET /api/v2/toggle_sb` — Toggle steam boiler
- `GET /api/v2/inc_dec` — Increment/decrement parameter
- `GET /api/v2/inc_dec_bb` — Adjust brew boiler
- `GET /api/v2/inc_dec_sb` — Adjust steam boiler
- `GET /api/v2/language` — Language setting
- `GET /api/v2/overview_single` — Single-value overview (used for set temperatures)
- `GET /api/v2/system/serial` — Serial number
- `GET /api/v2/system/reset_serial` — Reset serial
- `GET /get_all_params` — All parameters (returns empty in observed session)
- `GET /api/brew_start` — Start a brew shot

## Web UI Pages
- `/` — Overview (dashboard)
- `/machine` — Machine settings
- `/brewgroup` — Brew group settings
- `/brewboiler` — Brew boiler settings
- `/scripts` — Script management
- `/paddle` — Paddle configuration
- `/pid` — PID tuning
- `/steamboiler` — Steam boiler settings

## HA Integration (confirmed 2026-07-10)

### Configuration Architecture

The Xenia integration uses a hybrid approach:
1. **Modern `rest:` integration** (in `configuration.yaml`) — polls `/api/v2/overview` and `/api/v2/overview_single` for raw machine data
2. **Template entities** (in `configuration.yaml` under `template:`) — derive human-readable sensors from the REST sensor attributes
3. **`rest_command:`** — sends control commands to the machine
4. **Manual device registry entry** — groups all entities under one "Xenia" device (see "Device Creation" below)

### Working Entities
| Entity | Type | Source |
|--------|------|--------|
| `sensor.xenia_machine_data` | REST sensor | `/api/v2/overview` (modern `rest:` syntax) |
| `sensor.xenia_set_temperatures` | REST sensor | `/api/v2/overview_single` (modern `rest:` syntax) |
| `sensor.xenia_status` | Template sensor | Derived from `MA_STATUS` (On/Off) |
| `sensor.brew_group_temperature` | Template sensor | `BG_SENS_TEMP_A` |
| `sensor.brew_boiler_temperature` | Template sensor | `BB_SENS_TEMP_A` |
| `sensor.brew_group_set_temperature` | Template sensor | Set temp |
| `switch.xenia_power_2` | Template switch | Calls `rest_command.xenia_machine_control` |
| `rest_command.xenia_machine_control` | REST command | `POST /api/v2/machine/control` |

### Broken/Orphaned Entities
| Entity | Issue |
|--------|-------|
| `sensor.xenia_current_power_2` | `unavailable` — derived from broken integration sensor |
| `sensor.xenia_total_energy_2` | `unavailable` — derived from broken integration sensor |
| `switch.xenia_power` | `unavailable`, `restored: true` — old entity, superseded by `switch.xenia_power_2` |

### Device Creation (confirmed 2026-07-10)

**Challenge:** `device_info` is NOT supported in `rest:` or `template:` YAML integrations. HA rejects it with "Invalid config for 'rest': 'device_info' is an invalid option".

**Solution:** Manually create the device in `.storage/core.device_registry` and link entities via `.storage/core.entity_registry`, using SSH access to the HA container (see "HAOS Advanced SSH Addon Access" in SKILL.md).

**Result:** Device "Xenia" (ID: `42aef3df-3746-41bd-9292-e987a64d42d0`) created with:
- Manufacturer: Xenia Coffee
- Model: Xenia Espresso
- Serial: 313253795029
- SW Version: 3.9
- Configuration URL: http://10.0.50.128

5 entities linked to the device: `switch.xenia_power`, `switch.xenia_power_2`, `sensor.xenia_status`, `sensor.xenia_current_power_2`, `sensor.xenia_total_energy_2`.

**Key learnings:**
1. `device_info` does NOT work in `rest:` or `template:` YAML — confirmed by HA error messages
2. Manual `.storage/` device entries ARE persisted across restarts IF all required fields are present (see SKILL.md pitfall for complete field list)
3. Entity-to-device links in `.storage/core.entity_registry` also survive restarts
4. The `rest:` modern syntax (vs legacy `sensor: - platform: rest`) was adopted during this process — cleaner structure but still no `device_info` support

### Power Switch Verification (confirmed 2026-06-29)
`switch.xenia_power_2` turn_on/turn_off both work via HA API. Verified end-to-end:
1. `POST /api/services/switch/turn_on {"entity_id":"switch.xenia_power_2"}` → switch state = `on`
2. Device API confirms: `MA_STATUS: 1`, `MA_CUR_PWR: 8.3W`, temp rising (39.4°C → 48.4°C)
3. `POST /api/services/switch/turn_off {"entity_id":"switch.xenia_power_2"}` → switch state = `off`
4. Device API confirms: `MA_STATUS: 0`

Note: `rest_command.xenia_machine_control` also toggles power but returns empty response (not an error). The `switch.xenia_power_2` REST switch is the cleaner interface.

### Alexa Exposure
`switch.xenia_power_2` is NOT exposed to Alexa via HA Cloud. The old `switch.xenia_power` (now dead) was likely the previously exposed entity. Fix: add `switch.xenia_power_2` to HA Cloud Alexa exposure list, or use `switch_as_x` to create a light entity. Cannot fix via API alone — Alexa exposure list is managed in HA UI.

## Configuration YAML (Modern rest: Syntax)

The `configuration.yaml` uses modern `rest:` integration syntax (converted from legacy `sensor: - platform: rest`):

```yaml
rest:
  - resource: http://10.0.50.128/api/v2/overview
    method: GET
    timeout: 30
    scan_interval: 1
    sensor:
      - name: "Xenia Machine Data"
        unique_id: xenia_machine_data
        value_template: >-
          {% if value_json is defined %}OK{% else %}Error{% endif %}
        json_attributes:
          - MA_STATUS
          - BG_SENS_TEMP_A
          - BB_SENS_TEMP_A
          - PU_SENS_PRESS
          - SB_SENS_PRESS
          - MA_CUR_PWR
          - MA_ENERGY_TOTAL_KWH

  - resource: http://10.0.50.128/api/v2/overview_single
    method: GET
    timeout: 30
    scan_interval: 60
    sensor:
      - name: "Xenia Set Temperatures"
        unique_id: xenia_set_temperatures
        value_template: >-
          {% if value_json is defined %}OK{% else %}Error{% endif %}
        json_attributes:
          - BG_SET_TEMP
```

Template entities derive from these REST sensors and a template switch controls power via `rest_command`.
