docs(wiki): add full HTTP API reference

2026-04-18 16:48:32 +00:00
parent 107be8cf68
commit 70b3e2a847
+453
@@ -0,0 +1,453 @@
# HTTP API
`tvctl` exposes a loopback HTTP API for local automation and dashboards.
## Base URL
- Default: `http://127.0.0.1:7272/v1`
- Configurable with `daemon.http_host` and `daemon.http_port`
- API version prefix is always `/v1`
## Response Envelope
Successful responses:
```json
{
"ok": true,
"data": {}
}
```
Error responses:
```json
{
"ok": false,
"error": {
"code": "device_not_found",
"message": "No known device matched 'living-room'.",
"hint": "Run tvctl device list to see known devices."
}
}
```
Use `error.code` for automation logic. `message` and `hint` are human-facing.
## Device Identifiers
Anywhere `{id}` appears, you can use either:
- tvctl UUID
- Friendly device name
Example:
- `GET /v1/devices/3e2f7e8b-2d5e-4eb5-aef3-b2c4f2b2f17a/state`
- `GET /v1/devices/living-room/state`
## Endpoints
### `GET /v1/devices`
List known devices.
Example:
```bash
curl http://127.0.0.1:7272/v1/devices
```
Returns `data` as `Device[]`.
---
### `POST /v1/devices/discover`
Run discovery immediately and merge results into registry.
Example:
```bash
curl -X POST http://127.0.0.1:7272/v1/devices/discover
```
Returns `data`:
```json
{
"devices": []
}
```
---
### `GET /v1/devices/{id}`
Get one known device by UUID or friendly name.
Example:
```bash
curl http://127.0.0.1:7272/v1/devices/living-room
```
Returns `data` as `Device`.
---
### `DELETE /v1/devices/{id}`
Remove one device from the registry.
Example:
```bash
curl -X DELETE http://127.0.0.1:7272/v1/devices/bedroom
```
Returns `data` as removed `Device`.
---
### `GET /v1/devices/{id}/state`
Fetch live state for one device.
Example:
```bash
curl http://127.0.0.1:7272/v1/devices/living-room/state
```
Returns `data`:
```json
{
"device": {},
"state": {}
}
```
---
### `GET /v1/devices/{id}/apps`
List installed apps for device platform from cache.
Example:
```bash
curl http://127.0.0.1:7272/v1/devices/living-room/apps
```
Returns `data`:
```json
{
"platform": "roku",
"apps": []
}
```
---
### `POST /v1/devices/{id}/apps/launch`
Launch an app by normalized app id, app name, or platform id.
Request body:
```json
{
"app": "jellyfin"
}
```
Example:
```bash
curl -X POST http://127.0.0.1:7272/v1/devices/living-room/apps/launch \
-H 'Content-Type: application/json' \
-d '{"app":"jellyfin"}'
```
Returns action payload in `data`.
---
### `POST /v1/devices/{id}/apps/stop`
Stop the currently active app.
Example:
```bash
curl -X POST http://127.0.0.1:7272/v1/devices/living-room/apps/stop
```
Returns action payload in `data`.
---
### `POST /v1/devices/{id}/apps/refresh`
Refresh cached app catalog from live device.
Request body is optional.
- Without body: merge/refresh cache
- With body:
```json
{
"clear": true
}
```
`clear=true` clears platform cache before refresh.
Examples:
```bash
curl -X POST http://127.0.0.1:7272/v1/devices/living-room/apps/refresh
curl -X POST http://127.0.0.1:7272/v1/devices/living-room/apps/refresh \
-H 'Content-Type: application/json' \
-d '{"clear":true}'
```
Returns action payload in `data`.
---
### `POST /v1/devices/{id}/remote/key`
Send a single normalized key.
Request body:
```json
{
"key": "home"
}
```
Example:
```bash
curl -X POST http://127.0.0.1:7272/v1/devices/living-room/remote/key \
-H 'Content-Type: application/json' \
-d '{"key":"volume-up"}'
```
Returns action payload in `data`.
---
### `POST /v1/devices/{id}/remote/sequence`
Send multiple normalized keys with per-key delay.
Request body:
```json
{
"keys": ["home", "home", "up"],
"delay_ms": 200
}
```
`delay_ms` defaults to `200` when omitted.
Example:
```bash
curl -X POST http://127.0.0.1:7272/v1/devices/living-room/remote/sequence \
-H 'Content-Type: application/json' \
-d '{"keys":["home","home","home","up"],"delay_ms":200}'
```
Returns action payload in `data`.
---
### `POST /v1/devices/{id}/dev/install`
Sideload a development package ZIP (Roku developer mode).
Content type: `multipart/form-data`
Form field:
- `archive`: zip file bytes
Example:
```bash
curl -X POST http://127.0.0.1:7272/v1/devices/living-room/dev/install \
-F archive=@./channel.zip
```
Returns action payload in `data`.
---
### `POST /v1/devices/{id}/dev/reload`
Reload currently sideloaded development package.
Example:
```bash
curl -X POST http://127.0.0.1:7272/v1/devices/living-room/dev/reload
```
Returns action payload in `data`.
---
### `GET /v1/devices/{id}/dev/logs`
Fetch recent device developer logs.
Example:
```bash
curl http://127.0.0.1:7272/v1/devices/living-room/dev/logs
```
Returns `data`:
```json
{
"device": {},
"lines": []
}
```
---
### `GET /v1/daemon/status`
Get daemon health and runtime status.
Example:
```bash
curl http://127.0.0.1:7272/v1/daemon/status
```
Returns `data`:
```json
{
"pid": 12345,
"socket": "/run/user/1000/tvctl.sock",
"http_enabled": true,
"http_host": "127.0.0.1",
"http_port": 7272,
"device_count": 1,
"default_device": "living-room"
}
```
---
### `GET /v1/config`
Read effective config from disk.
Notes:
- `dev.roku_password` is redacted in API responses.
Example:
```bash
curl http://127.0.0.1:7272/v1/config
```
Returns `data` as full config object.
---
### `PATCH /v1/config`
Patch config using flat key/value pairs.
Rules:
- Keys are dotted paths (for example `daemon.http_port`)
- Values must be string, number, boolean, or `null`
Example:
```bash
curl -X PATCH http://127.0.0.1:7272/v1/config \
-H 'Content-Type: application/json' \
-d '{"daemon.cors_enabled":true,"daemon.cors_allowed_origins":"http://127.0.0.1:8080"}'
```
Returns same shape as config reload result in `data`.
---
### `POST /v1/config/reload`
Reload daemon config from disk.
Example:
```bash
curl -X POST http://127.0.0.1:7272/v1/config/reload
```
Returns `data`:
```json
{
"config": {},
"restart_required": []
}
```
## Key Names
Common key names:
- `home`, `back`, `up`, `down`, `left`, `right`, `select`
- `play`, `pause`, `play-pause`, `stop`, `rewind`, `fast-forward`, `replay`, `skip`
- `volume-up`, `volume-down`, `mute`
- `power`, `power-on`, `power-off`
- `channel-up`, `channel-down`
- `input-hdmi1`, `input-hdmi2`, `input-hdmi3`, `input-hdmi4`, `input-av`, `input-tuner`
- `search`, `info`, `options`
- `literal:<text>` for raw adapter literal keys
## HTTP Status Mapping
Typical statuses:
- `200 OK` success
- `400 Bad Request` invalid key, invalid payload, ambiguous app, unsupported patch values
- `404 Not Found` unknown device/default device missing
- `500 Internal Server Error` transport/adapter/internal failures
## CORS Notes
Browser clients require CORS config:
```toml
[daemon]
cors_enabled = true
cors_allowed_origins = ["http://127.0.0.1:8080", "http://localhost:8080"]
```
Then reload:
```bash
tvctl config reload
```
Origin must match exactly (`http://127.0.0.1:8080` is not `http://0.0.0.0:8080`).