# API Contract

The new client should wrap all backend calls in a dedicated API layer. UI
components should not call `fetch` directly.

## Transport

Current dev transport:

```text
GET|POST {baseUrl}/proxy.php?path=/api/v1/...
```

Current backend base from `webclient/config.php`:

```text
http://smart-home-serv.local
```

## Common Response Shape

Success:

```json
{
  "status": true,
  "data": {}
}
```

Error:

```json
{
  "status": false,
  "error_alias": "device_request_fail",
  "failed_fields": [],
  "msg": "Устройство не отвечает"
}
```

The new API layer should normalize responses into one result shape:

```js
// success
{ ok: true, data, meta }

// failure
{ ok: false, error, meta }
```

## Devices

| Method | Path | Current Use |
| --- | --- | --- |
| GET | `/api/v1/devices/list` | Devices list. |
| GET | `/api/v1/devices/id/{id}` | Device DB info. |
| GET | `/api/v1/devices/id/{id}/info` | Device DB info plus live `/about`. |
| GET | `/api/v1/devices/id/{id}/status` | Live device state. |
| GET | `/api/v1/devices/scanning/all` | Scan all devices in local network range. |
| GET | `/api/v1/devices/scanning/setup` | Scan setup-mode devices. |
| POST | `/api/v1/devices/setup/new-device` | Register a setup-mode device. |
| GET | `/api/v1/devices/id/{id}/reboot` | Reboot one device. |
| POST | `/api/v1/devices/resetup` | Reset/rebind device token. |
| POST | `/api/v1/devices/reset` | Reset device. |
| POST | `/api/v1/devices/update-name` | Update device name. |
| POST | `/api/v1/devices/update-description` | Update device description. |
| POST | `/api/v1/devices/update-alias` | Update device alias. |
| POST | `/api/v1/devices/place-in-area` | Assign device to area. |
| GET | `/api/v1/devices/id/{id}/unassign-from-area` | Remove device from area. |

Device state rendering depends on `device_type`:

- `relay` expects `channels[]` with `id` and `state`.
- `button` expects `channels[]` with `id` and `indicator`.
- `sensor` expects `sensors.light`, `temperature`, `pressure`, `humidity`,
  `radar`, and `microphone`.
- `hatch` expects `hatch.state` and `hatch.position_pct`.

## Scripts

| Method | Path | Current Use |
| --- | --- | --- |
| GET | `/api/v1/scripts/actions/list` | Action script cards. |
| POST | `/api/v1/scripts/actions/run` | Run action script by alias. |
| GET | `/api/v1/scripts/regular/list` | Regular scripts table. |
| GET | `/api/v1/scripts/regular/alias/{alias}/enable` | Enable regular script. |
| GET | `/api/v1/scripts/regular/alias/{alias}/disable` | Disable regular script. |
| GET | `/api/v1/scripts/scopes/list` | Scopes table. |
| GET | `/api/v1/scripts/scopes/name/{name}/enable` | Enable scope. |
| GET | `/api/v1/scripts/scopes/name/{name}/disable` | Disable scope. |
| GET | `/api/v1/scripts/scopes/name/{name}/remove` | Remove scope. |
| GET | `/api/v1/scripts/scopes/name/{filename}` | Get scope source by filename/name. |
| POST | `/api/v1/scripts/scopes/new` | Create scope. |
| POST | `/api/v1/scripts/scopes/update` | Update scope. |
| POST | `/api/v1/scripts/place-in-area` | Assign script to area. |
| GET | `/api/v1/scripts/id/{id}/unassign-from-area` | Remove script from area. |

## Areas

| Method | Path | Current Use |
| --- | --- | --- |
| GET | `/api/v1/areas/list` | Areas tree and favorites. |
| GET | `/api/v1/areas/id/{area_id}/list` | Area inner list. |
| POST | `/api/v1/areas/new-area` | Create area. |
| GET | `/api/v1/areas/id/{area_id}/remove` | Remove area. |
| POST | `/api/v1/areas/place-in-area` | Move area under another area. |
| POST | `/api/v1/areas/update-display-name` | Rename area display name. |
| POST | `/api/v1/areas/update-alias` | Update area alias. |
| GET | `/api/v1/areas/id/{area_id}/devices` | Devices in area. |
| GET | `/api/v1/areas/id/{area_id}/scripts` | Scripts in area. |
| GET | `/api/v1/areas/id/{id}/unassign-from-area` | Remove area from parent. |
| GET | `/api/v1/areas/types/list` | Allowed area types. |
| GET | `/api/v1/areas/reboot_devices` | Reboot all devices. |
| GET | `/api/v1/areas/id/{area_id}/reboot_devices` | Reboot devices in area. |

## Reliability Requirements

- Device status loading must be isolated per device.
- A failed device status request must not break the full screen.
- Device status requests should have a concurrency limit.
- The UI should distinguish backend error, network/proxy error, and device offline.
- API callback/consumer errors must not be treated as transport failures.
