2026-04-03 16:23:15 +02:00
|
|
|
# REST API Cookbook
|
|
|
|
|
|
|
|
|
|
This page contains copy-paste examples for the Tuliprox Web UI REST API.
|
|
|
|
|
|
|
|
|
|
The examples use:
|
|
|
|
|
|
|
|
|
|
- `curl` for HTTP requests
|
|
|
|
|
- `jq` for token extraction and pretty-printing JSON
|
|
|
|
|
|
|
|
|
|
## Requirements
|
|
|
|
|
|
|
|
|
|
- Tuliprox is running in server mode
|
|
|
|
|
- the Web UI REST API is enabled
|
|
|
|
|
- `curl` and `jq` are installed
|
|
|
|
|
- you have a valid Web UI username and password
|
|
|
|
|
|
|
|
|
|
## Base URLs
|
|
|
|
|
|
|
|
|
|
By default, the login endpoint is:
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
http://localhost:8901/auth/token
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
If you configured a custom Web UI path such as `web`, the login endpoint becomes:
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
http://localhost:8901/web/auth/token
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The protected REST API lives below:
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
http://localhost:8901/api/v1
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
or, with a Web UI path:
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
http://localhost:8901/web/api/v1
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Example 1: Get a JWT token
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
#!/bin/bash
|
|
|
|
|
|
|
|
|
|
BASE_URL="http://localhost:8901"
|
|
|
|
|
USERNAME="admin"
|
|
|
|
|
PASSWORD="12345678"
|
|
|
|
|
|
|
|
|
|
TOKEN=$(curl -s -X POST "$BASE_URL/auth/token" \
|
|
|
|
|
-H 'accept: application/json' \
|
|
|
|
|
-H 'content-type: application/json' \
|
|
|
|
|
--data-raw "{\"username\":\"$USERNAME\",\"password\":\"$PASSWORD\"}" | jq -r '.token')
|
|
|
|
|
|
|
|
|
|
if [ "$TOKEN" = "null" ] || [ -z "$TOKEN" ]; then
|
|
|
|
|
echo "Error: no token available"
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
echo "$TOKEN"
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
If your local setup uses HTTPS with a self-signed certificate, add `--insecure` to the `curl` commands.
|
|
|
|
|
|
|
|
|
|
## Example 2: Query server status
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
#!/bin/bash
|
|
|
|
|
|
|
|
|
|
BASE_URL="http://localhost:8901"
|
|
|
|
|
USERNAME="admin"
|
|
|
|
|
PASSWORD="12345678"
|
|
|
|
|
|
|
|
|
|
TOKEN=$(curl -s -X POST "$BASE_URL/auth/token" \
|
|
|
|
|
-H 'accept: application/json' \
|
|
|
|
|
-H 'content-type: application/json' \
|
|
|
|
|
--data-raw "{\"username\":\"$USERNAME\",\"password\":\"$PASSWORD\"}" | jq -r '.token')
|
|
|
|
|
|
|
|
|
|
curl -s -X GET "$BASE_URL/api/v1/status" \
|
|
|
|
|
-H "Authorization: Bearer $TOKEN" \
|
|
|
|
|
-H "Accept: application/json" | jq .
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Typical use:
|
|
|
|
|
|
|
|
|
|
- verify that login works
|
|
|
|
|
- use as a simple health and diagnostics check
|
|
|
|
|
- inspect active users, active provider connections, cache state, and current server time
|
|
|
|
|
|
|
|
|
|
From this point onward, the examples use:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
TOKEN="PUT_YOUR_TOKEN_HERE"
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
This is only to keep the examples shorter and easier to copy-paste.
|
|
|
|
|
Example 1 above already shows how to obtain the JWT token, so it is not repeated in every script block below.
|
|
|
|
|
|
|
|
|
|
## Example 3: List active streams
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
#!/bin/bash
|
|
|
|
|
|
|
|
|
|
BASE_URL="http://localhost:8901"
|
|
|
|
|
TOKEN="PUT_YOUR_TOKEN_HERE"
|
|
|
|
|
|
|
|
|
|
curl -s -X GET "$BASE_URL/api/v1/streams" \
|
|
|
|
|
-H "Authorization: Bearer $TOKEN" \
|
|
|
|
|
-H "Accept: application/json" | jq .
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Typical use:
|
|
|
|
|
|
|
|
|
|
- inspect currently active streams
|
|
|
|
|
- see who is connected
|
|
|
|
|
- correlate user activity with provider slot pressure
|
|
|
|
|
|
|
|
|
|
## Example 4: Query stream history summary
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
#!/bin/bash
|
|
|
|
|
|
|
|
|
|
BASE_URL="http://localhost:8901"
|
|
|
|
|
TOKEN="PUT_YOUR_TOKEN_HERE"
|
|
|
|
|
|
|
|
|
|
curl -s -X GET "$BASE_URL/api/v1/stream-history/summary?from=2026-04-01&to=2026-04-03" \
|
|
|
|
|
-H "Authorization: Bearer $TOKEN" \
|
|
|
|
|
-H "Accept: application/json" | jq .
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Typical use:
|
|
|
|
|
|
|
|
|
|
- get an aggregated view over recent stream activity
|
|
|
|
|
- inspect disconnect patterns and provider churn
|
|
|
|
|
- verify that stream history collection is working
|
|
|
|
|
|
|
|
|
|
## Example 5: Query QoS snapshots
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
#!/bin/bash
|
|
|
|
|
|
|
|
|
|
BASE_URL="http://localhost:8901"
|
|
|
|
|
TOKEN="PUT_YOUR_TOKEN_HERE"
|
|
|
|
|
|
|
|
|
|
curl -s -X GET "$BASE_URL/api/v1/qos-snapshots" \
|
|
|
|
|
-H "Authorization: Bearer $TOKEN" \
|
|
|
|
|
-H "Accept: application/json" | jq .
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Typical use:
|
|
|
|
|
|
|
|
|
|
- inspect per-stream reliability snapshots
|
|
|
|
|
- compare `24h`, `7d`, and `30d` quality windows
|
|
|
|
|
- prepare later failover and ranking analysis
|
|
|
|
|
|
|
|
|
|
## Example 6: Inspect a download target before queueing
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
#!/bin/bash
|
|
|
|
|
|
|
|
|
|
BASE_URL="http://localhost:8901"
|
|
|
|
|
TOKEN="PUT_YOUR_TOKEN_HERE"
|
|
|
|
|
URL_TO_DOWNLOAD="https://example.invalid/file.mp4"
|
|
|
|
|
|
|
|
|
|
curl -s -G "$BASE_URL/api/v1/file/download/info" \
|
|
|
|
|
--data-urlencode "url=$URL_TO_DOWNLOAD" \
|
|
|
|
|
-H "Authorization: Bearer $TOKEN" \
|
|
|
|
|
-H "Accept: application/json" | jq .
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Typical use:
|
|
|
|
|
|
|
|
|
|
- inspect filename and metadata before queueing
|
|
|
|
|
- verify that the remote file is reachable
|
2026-09-01 09:23:52 -05:00
|
|
|
- test `recording.read` access
|
2026-04-03 16:23:15 +02:00
|
|
|
|
|
|
|
|
## Example 7: Queue a file download
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
#!/bin/bash
|
|
|
|
|
|
|
|
|
|
BASE_URL="http://localhost:8901"
|
|
|
|
|
TOKEN="PUT_YOUR_TOKEN_HERE"
|
|
|
|
|
|
|
|
|
|
curl -s -X POST "$BASE_URL/api/v1/file/download" \
|
|
|
|
|
-H "Authorization: Bearer $TOKEN" \
|
|
|
|
|
-H "Accept: application/json" \
|
|
|
|
|
-H "Content-Type: application/json" \
|
|
|
|
|
--data-raw '{
|
|
|
|
|
"url": "https://example.invalid/file.mp4",
|
|
|
|
|
"filename": "example.mp4",
|
|
|
|
|
"input_name": null,
|
|
|
|
|
"priority": null
|
|
|
|
|
}' | jq .
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Typical use:
|
|
|
|
|
|
|
|
|
|
- queue a normal background download
|
|
|
|
|
- confirm that duplicate queue requests return the existing task instead of creating a second one
|
2026-09-01 09:23:52 -05:00
|
|
|
- test `recording.manage` access
|
2026-04-03 16:23:15 +02:00
|
|
|
|
|
|
|
|
## Example 8: Trigger a playlist update
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
#!/bin/bash
|
|
|
|
|
|
|
|
|
|
BASE_URL="http://localhost:8901"
|
|
|
|
|
TOKEN="PUT_YOUR_TOKEN_HERE"
|
|
|
|
|
|
|
|
|
|
curl -s -X POST "$BASE_URL/api/v1/playlist/update" \
|
|
|
|
|
-H "Authorization: Bearer $TOKEN" \
|
|
|
|
|
-H "Accept: application/json" \
|
|
|
|
|
-H "Content-Type: application/json" \
|
|
|
|
|
--data-raw '["main"]'
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Typical use:
|
|
|
|
|
|
|
|
|
|
- trigger a manual processing run for one or more targets
|
|
|
|
|
- verify `playlist.write` permission
|
|
|
|
|
- integrate Tuliprox into external automation
|
|
|
|
|
|
2026-07-20 14:58:06 +02:00
|
|
|
## Example 9: Preview a Stalker live input in the Web UI playlist API
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
#!/bin/bash
|
|
|
|
|
|
|
|
|
|
BASE_URL="http://localhost:8901"
|
|
|
|
|
TOKEN="PUT_YOUR_TOKEN_HERE"
|
|
|
|
|
|
|
|
|
|
curl -s -X POST "$BASE_URL/api/v1/playlist/live" \
|
|
|
|
|
-H "Authorization: Bearer $TOKEN" \
|
|
|
|
|
-H "Accept: application/json" \
|
|
|
|
|
-H "Content-Type: application/json" \
|
|
|
|
|
--data-raw '{"Input":"stalker"}' | jq .
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Typical use:
|
|
|
|
|
|
|
|
|
|
- verify that a configured Stalker input handshakes and returns playlist preview rows
|
|
|
|
|
- confirm that the Web UI playlist explorer can inspect Stalker live content
|
|
|
|
|
- distinguish preview/catalog problems from later playback-resolution problems
|
|
|
|
|
|
|
|
|
|
Notes:
|
|
|
|
|
|
|
|
|
|
- Replace `"stalker"` with the configured input name.
|
|
|
|
|
- The preview endpoint returns catalog items. Actual playback can still require Stalker `create_link` resolution later, depending
|
|
|
|
|
on your `stalker_pre_resolve_playback` / `stalker_runtime_resolve_playback` settings.
|
|
|
|
|
- If a Stalker item has not been materialized yet, Tuliprox no longer exposes the raw portal `cmd` as the playlist URL. Runtime
|
|
|
|
|
playback resolves a real media URL later through the reverse-proxy path.
|
|
|
|
|
- Expired temp links are refreshed automatically when `stalker_runtime_resolve_playback` is enabled. Only portal-specific extra
|
|
|
|
|
header/cookie requirements remain a possible follow-up.
|
|
|
|
|
- Runtime refresh only produces `http`/`https` playback URLs; Stalker `rtmp://` / `rtsp://` commands are rejected explicitly rather
|
|
|
|
|
than proxied half-supported.
|
|
|
|
|
|
2026-08-21 17:50:12 +05:00
|
|
|
## Example 10: Dry-run a filter expression against a target
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
#!/bin/bash
|
|
|
|
|
|
|
|
|
|
BASE_URL="http://localhost:8901"
|
|
|
|
|
TOKEN="PUT_YOUR_TOKEN_HERE"
|
|
|
|
|
|
|
|
|
|
curl -s -X POST "$BASE_URL/api/v1/playlist/filter/preview" \
|
|
|
|
|
-H "Authorization: Bearer $TOKEN" \
|
|
|
|
|
-H "Content-Type: application/json" \
|
|
|
|
|
--data-raw '{"target": 1, "filter": "Group ~ \"^DE.*\" AND NOT Title CONTAINS \"Shopping\"", "limit": 10}' | jq .
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Typical use:
|
|
|
|
|
|
|
|
|
|
- test a filter DSL expression against a target's stored playlist before writing it into `source.yml`
|
|
|
|
|
- see matched/total counts overall and per cluster (live/vod/series)
|
|
|
|
|
- inspect sample matched and excluded channels to verify the expression does what you expect
|
|
|
|
|
|
|
|
|
|
Notes:
|
|
|
|
|
|
|
|
|
|
- `target` is the numeric target id (same id the playlist explorer uses).
|
|
|
|
|
- `filter` supports the full filter DSL including `!TEMPLATE!` references from your configured templates.
|
|
|
|
|
- Optional `limit` caps the sample lists (default 25, max 50); optional `match_as_ascii` mirrors the target option.
|
|
|
|
|
- An invalid filter expression returns HTTP 422 with `{"error": "...", "line": n, "column": n}`; `line`/`column`
|
|
|
|
|
are `null` for semantic errors without a source position (e.g. an invalid regex value).
|
|
|
|
|
- The preview reads the target's already-processed playlist; it never contacts providers or triggers an update.
|
|
|
|
|
|
2026-04-03 16:23:15 +02:00
|
|
|
## Available `/api/v1` Endpoints
|
|
|
|
|
|
|
|
|
|
This is a compact operator-oriented overview of the `/api/v1` REST API groups currently registered by the backend.
|
|
|
|
|
|
|
|
|
|
### System and diagnostics
|
|
|
|
|
|
|
|
|
|
| Method | Path | Purpose |
|
|
|
|
|
| --- | --- | --- |
|
2026-08-22 21:52:19 +05:00
|
|
|
| `GET` | `/healthcheck` | Liveness probe — 200 while the process is running. Used by Docker via the `--healthcheck` CLI flag. |
|
|
|
|
|
| `GET` | `/ready` | Readiness probe — 200 when at least one input group has spare connection capacity; 503 when every input group is exhausted. |
|
2026-04-03 16:23:15 +02:00
|
|
|
| `GET` | `/api/v1/status` | Server status, version, active users, provider connections, cache state |
|
|
|
|
|
| `GET` | `/api/v1/streams` | Current active streams |
|
|
|
|
|
| `GET` | `/api/v1/ipinfo` | External IPv4/IPv6 check if configured |
|
|
|
|
|
| `GET` | `/api/v1/stream-history` | Query raw persisted stream history |
|
|
|
|
|
| `GET` | `/api/v1/stream-history/summary` | Aggregated stream history summary |
|
|
|
|
|
| `GET` | `/api/v1/qos-snapshots` | List QoS snapshots |
|
|
|
|
|
| `GET` | `/api/v1/qos-snapshots/{stream_identity_key}` | QoS detail for one stream |
|
|
|
|
|
| `GET` | `/api/v1/geoip/update` | Trigger GeoIP DB update |
|
|
|
|
|
|
|
|
|
|
### Downloads and recordings
|
|
|
|
|
|
2026-08-21 17:50:12 +05:00
|
|
|
| Method | Path | Purpose |
|
|
|
|
|
| -------- |------------------------------------------------------|---------------------------------------------------------------------------------|
|
|
|
|
|
| `GET` | `/api/v1/file/download/info` | Inspect remote file/download info |
|
|
|
|
|
| `POST` | `/api/v1/file/download` | Queue a file download |
|
|
|
|
|
| `POST` | `/api/v1/file/record` | Queue a live recording |
|
|
|
|
|
| `POST` | `/api/v1/file/download/pause` | Pause a queued or active download |
|
|
|
|
|
| `POST` | `/api/v1/file/download/resume` | Resume a paused download |
|
|
|
|
|
| `POST` | `/api/v1/file/download/cancel` | Cancel a queued or active download |
|
|
|
|
|
| `POST` | `/api/v1/file/download/remove` | Remove a task from the download database |
|
|
|
|
|
| `POST` | `/api/v1/file/download/retry` | Retry a failed download |
|
|
|
|
|
| `GET` | `/api/v1/recording/tasks` | List visible DVR tasks |
|
|
|
|
|
| `POST` | `/api/v1/recording/tasks` | Create a DVR recording task from server-owned source ids |
|
|
|
|
|
| `PATCH` | `/api/v1/recording/tasks/{id}` | Edit an upcoming DVR recording |
|
|
|
|
|
| `POST` | `/api/v1/recording/tasks/{id}/cancel` | Cancel an active, queued, or scheduled DVR recording |
|
|
|
|
|
| `DELETE` | `/api/v1/recording/tasks/{id}` | Delete a finished DVR recording through the safe deletion lifecycle |
|
|
|
|
|
| `POST` | `/api/v1/recording/conflicts/preview` | Advisory conflict preview (severity, optional provider scope, overlap segments) |
|
|
|
|
|
| `GET` | `/api/v1/recording/quota` | Read the caller's private quota and shared DVR usage |
|
|
|
|
|
| `GET` | `/api/v1/recording/rules` | List visible recurring recording rules |
|
|
|
|
|
| `POST` | `/api/v1/recording/rules` | Create a weekly recurring recording rule |
|
|
|
|
|
| `PATCH` | `/api/v1/recording/rules/{id}` | Edit a recurring recording rule |
|
|
|
|
|
| `DELETE` | `/api/v1/recording/rules/{id}?future=retain\|cancel` | Delete a recurring recording rule |
|
|
|
|
|
|
|
|
|
|
#### DVR WebSocket protocol
|
|
|
|
|
|
|
|
|
|
The DVR layer ships its own scoped protocol messages on the same WebSocket connection as the rest of the
|
|
|
|
|
backend. The frontend sends `ProtocolMessage::RecordingSnapshotRequest` to subscribe and receives:
|
|
|
|
|
|
|
|
|
|
- `ProtocolMessage::RecordingSnapshotResponse { revision, tasks }` — the full filtered task list for the
|
|
|
|
|
caller's session, sent on connect and after every mutation the session is permitted to see.
|
|
|
|
|
- `ProtocolMessage::RecordingDeltaResponse { revision, tasks }` — a smaller diff when only a few tasks
|
|
|
|
|
changed.
|
|
|
|
|
|
|
|
|
|
The frontend never polls. After a successful `POST /api/v1/recording/tasks` it relies on the next
|
|
|
|
|
`RecordingSnapshotResponse` to update its view. Rule lists are refreshed by hooking into
|
|
|
|
|
`EventMessage::RecordingSnapshot` and re-calling `GET /api/v1/recording/rules`; a dedicated
|
|
|
|
|
`RecordingRulesChanged` event is a planned follow-up but not currently shipped.
|
|
|
|
|
|
|
|
|
|
#### DVR conflict preview
|
|
|
|
|
|
|
|
|
|
`POST /api/v1/recording/conflicts/preview` is **advisory only** — the response carries a severity bucket
|
|
|
|
|
(`none` / `soft` / `hard`) plus optional provider scope and overlap segments, but the server does not
|
|
|
|
|
reject the create call based on it. The frontend renders the preview as a hint next to the recording
|
|
|
|
|
form's scheduled interval, never as a hard block.
|
|
|
|
|
|
|
|
|
|
#### `POST /api/v1/file/record` (deprecated)
|
|
|
|
|
|
|
|
|
|
The legacy `POST /api/v1/file/record` endpoint is admin-gated and **scheduled for removal in the next
|
|
|
|
|
major version**. It returns `recording_forbidden` for non-admin principals. New code should call
|
|
|
|
|
`POST /api/v1/recording/tasks` with a `CreateRecordingTaskBody` payload.
|
2026-04-03 16:23:15 +02:00
|
|
|
|
|
|
|
|
### Playlist and web-player helpers
|
|
|
|
|
|
|
|
|
|
| Method | Path | Purpose |
|
|
|
|
|
| --- | --- | --- |
|
2026-07-20 14:58:06 +02:00
|
|
|
| `POST` | `/api/v1/playlist/live` | Query live playlist content for the Web UI, including Stalker inputs |
|
2026-04-03 16:23:15 +02:00
|
|
|
| `POST` | `/api/v1/playlist/vod` | Query VOD playlist content |
|
|
|
|
|
| `POST` | `/api/v1/playlist/series` | Query series playlist content |
|
|
|
|
|
| `POST` | `/api/v1/playlist/resolve_url` | Resolve provider-backed stream URLs |
|
|
|
|
|
| `POST` | `/api/v1/playlist/update` | Trigger target updates |
|
|
|
|
|
| `POST` | `/api/v1/playlist/epg` | Query EPG data for the Web UI |
|
|
|
|
|
| `POST` | `/api/v1/playlist/series_info/{virtual_id}/{provider_id}` | Series metadata lookup |
|
|
|
|
|
| `POST` | `/api/v1/playlist/series/episode/{virtual_id}` | Episode item lookup |
|
2026-08-21 17:50:12 +05:00
|
|
|
| `POST` | `/api/v1/playlist/filter/preview` | Dry-run a filter DSL expression against a target's stored playlist |
|
2026-04-03 16:23:15 +02:00
|
|
|
| `GET` | `/api/v1/playlist/resource/{resource}` | Public resource access for playlist-related assets |
|
|
|
|
|
|
|
|
|
|
### Configuration
|
|
|
|
|
|
|
|
|
|
| Method | Path | Purpose |
|
|
|
|
|
| --- | --- | --- |
|
|
|
|
|
| `GET` | `/api/v1/config` | Read effective configuration |
|
|
|
|
|
| `GET` | `/api/v1/config/batchContent/{input_id}` | Inspect batch input content |
|
|
|
|
|
| `POST` | `/api/v1/config/xtream/login-info` | Test or inspect Xtream login information |
|
|
|
|
|
| `POST` | `/api/v1/config/main` | Save `config.yml` |
|
|
|
|
|
| `POST` | `/api/v1/config/sources` | Save `source.yml` |
|
|
|
|
|
| `GET` | `/api/v1/config/apiproxy` | Read `api-proxy.yml` |
|
|
|
|
|
| `PUT` | `/api/v1/config/apiproxy` | Save `api-proxy.yml` |
|
|
|
|
|
|
|
|
|
|
### API proxy users
|
|
|
|
|
|
|
|
|
|
| Method | Path | Purpose |
|
|
|
|
|
| --- | --- | --- |
|
|
|
|
|
| `POST` | `/api/v1/user/{target}` | Create a target user |
|
|
|
|
|
| `PUT` | `/api/v1/user/{target}` | Update or move a target user |
|
|
|
|
|
| `DELETE` | `/api/v1/user/{target}/{username}` | Delete a target user |
|
|
|
|
|
|
|
|
|
|
### Library
|
|
|
|
|
|
|
|
|
|
| Method | Path | Purpose |
|
|
|
|
|
| --- | --- | --- |
|
|
|
|
|
| `GET` | `/api/v1/library/status` | Local library status |
|
|
|
|
|
| `POST` | `/api/v1/library/scan` | Trigger a library scan |
|
|
|
|
|
| `GET` | `/api/v1/library/thumbnail/{uuid}` | Read a generated thumbnail |
|
|
|
|
|
|
|
|
|
|
### RBAC management
|
|
|
|
|
|
|
|
|
|
| Method | Path | Purpose |
|
|
|
|
|
| --- | --- | --- |
|
|
|
|
|
| `GET` | `/api/v1/rbac/users` | List Web UI users |
|
|
|
|
|
| `POST` | `/api/v1/rbac/users` | Create a Web UI user |
|
|
|
|
|
| `PUT` | `/api/v1/rbac/users/{username}` | Update a Web UI user |
|
|
|
|
|
| `DELETE` | `/api/v1/rbac/users/{username}` | Delete a Web UI user |
|
|
|
|
|
| `GET` | `/api/v1/rbac/groups` | List permission groups |
|
|
|
|
|
| `POST` | `/api/v1/rbac/groups` | Create a permission group |
|
|
|
|
|
| `PUT` | `/api/v1/rbac/groups/{name}` | Update a permission group |
|
|
|
|
|
| `DELETE` | `/api/v1/rbac/groups/{name}` | Delete a permission group |
|
|
|
|
|
| `GET` | `/api/v1/rbac/permissions` | List available permissions |
|
|
|
|
|
|
|
|
|
|
## Permissions
|
|
|
|
|
|
|
|
|
|
With Web UI authentication enabled, many endpoints require matching permissions such as:
|
|
|
|
|
|
|
|
|
|
- `system.read`
|
|
|
|
|
- `system.write`
|
|
|
|
|
- `playlist.read`
|
|
|
|
|
- `playlist.write`
|
|
|
|
|
- `config.read`
|
|
|
|
|
- `config.write`
|
|
|
|
|
- `source.read`
|
|
|
|
|
- `source.write`
|
|
|
|
|
- `user.read`
|
|
|
|
|
- `user.write`
|
|
|
|
|
- `library.read`
|
|
|
|
|
- `library.write`
|
2026-08-21 17:50:12 +05:00
|
|
|
- `recording.read`
|
2026-08-31 15:30:39 -05:00
|
|
|
- `recording.create`
|
|
|
|
|
- `recording.manage`
|
|
|
|
|
- `recording.delete`
|
2026-04-03 16:23:15 +02:00
|
|
|
|
|
|
|
|
If a request is rejected, verify the logged-in Web UI user's RBAC group assignments first.
|
2026-08-21 17:50:12 +05:00
|
|
|
|
|
|
|
|
> **See also:** the full [DVR Operator Reference](./operator/dvr.md) for the authorization matrix, identity-registry
|
|
|
|
|
> bootstrap, token refresh, recurring-rule matching + DST, cross-store reconciliation, at-most-once notification
|
|
|
|
|
> protocol, and the migration checklist.
|