mirror of
https://github.com/unshackle-dl/unshackle.git
synced 2026-11-14 21:15:06 +00:00
docs: restructure documentation into MkDocs Material site
This commit is contained in:
@@ -0,0 +1,237 @@
|
||||
# REST API Overview
|
||||
|
||||
unshackle ships with a built-in HTTP server. Alongside the command-line tool, you
|
||||
can run `unshackle serve` and drive the same download engine over a REST API:
|
||||
searching services, listing titles and tracks, queueing downloads, watching live
|
||||
progress, and browsing history, all as JSON over HTTP.
|
||||
|
||||
This page explains what the API is for, how to start the server, where it listens,
|
||||
and how the endpoints are organised. Later pages cover each area in depth.
|
||||
|
||||
!!! info "Who this section is for"
|
||||
The REST API is aimed at people building automation, dashboards, or remote
|
||||
clients on top of unshackle. If you only download the occasional title, the
|
||||
[command-line tool](../../guide/cli-reference.md) does everything the API does
|
||||
and is simpler to use. Reach for the API when you want a long-running service, a
|
||||
job queue, or a web front-end.
|
||||
|
||||
## What the API is for
|
||||
|
||||
The server exposes the same capabilities as the `dl` command, but as discrete HTTP
|
||||
calls you can script against:
|
||||
|
||||
- **Discovery**: list the services available on the server, run a service's search,
|
||||
and enumerate the titles and tracks behind a title ID.
|
||||
- **Downloading**: submit a download as a background *job*, then poll its status and
|
||||
live progress, cancel it, retry it, or bump it to the front of the queue.
|
||||
- **History and housekeeping**: read the log of finished jobs, inspect the server's
|
||||
effective (redacted) configuration, check external tool versions, and clear caches
|
||||
or temp files.
|
||||
- **Remote-download sessions**: a thin local client can authenticate against a
|
||||
service *on the server*, then pull titles, tracks, and segment info back, and proxy
|
||||
DRM licensing. This is how one machine with the credentials and CDMs can serve
|
||||
downloads to another. See [Remote Sessions](remote-sessions.md).
|
||||
|
||||
Because every download runs as a queued job in a separate worker process, the API is
|
||||
well suited to running unattended: submit work, come back later, and read the result.
|
||||
|
||||
## Running the server
|
||||
|
||||
Start the server with the `serve` command:
|
||||
|
||||
```shell title="Start the REST API on the default host and port"
|
||||
unshackle serve
|
||||
```
|
||||
|
||||
By default the server binds to `127.0.0.1:8786` and requires an API key on every
|
||||
request. It also serves the local Widevine and PlayReady CDM endpoints (for
|
||||
pywidevine / pyplayready clients) in addition to the REST API.
|
||||
|
||||
!!! warning "An API key is required by default"
|
||||
Unless you pass `--no-key`, the server needs an API secret configured under the
|
||||
`serve` section of your config. If none is set, `unshackle serve` refuses to
|
||||
start. See [Authentication](authentication.md) for how to set `api_secret` and
|
||||
how the `X-Secret-Key` header works.
|
||||
|
||||
### Common options
|
||||
|
||||
The `serve` command accepts the following flags:
|
||||
|
||||
| Option | Default | Effect |
|
||||
|---|---|---|
|
||||
| `-h`, `--host` | `127.0.0.1` | Address to bind to. Use `0.0.0.0` to accept connections from other machines. |
|
||||
| `-p`, `--port` | `8786` | Port to bind to. |
|
||||
| `--api-only` | off | Serve only the REST API, without the Widevine/PlayReady CDM HTTP endpoints. |
|
||||
| `--no-widevine` | off | Disable the Widevine CDM endpoints. Cannot be combined with `--api-only`. |
|
||||
| `--no-playready` | off | Disable the PlayReady CDM endpoints. Cannot be combined with `--api-only`. |
|
||||
| `--no-key` | off | Disable API-key authentication entirely; every request is allowed. |
|
||||
| `--remote-only` | off | Expose only the remote-session subset of routes. Implies `--api-only`. |
|
||||
| `--debug-api` | off | Include tracebacks and worker stderr in error responses. |
|
||||
| `--debug` | off | Enable debug-level logging. |
|
||||
| `--caddy` | off | Also launch [Caddy](https://caddyserver.com/) as a reverse proxy, using the `Caddyfile` in your user-config directory. |
|
||||
|
||||
```shell title="Serve the REST API only, on all interfaces"
|
||||
unshackle serve --api-only --host 0.0.0.0 --port 8786
|
||||
```
|
||||
|
||||
!!! danger "Binding to a public interface"
|
||||
`--no-key` disables authentication completely. Anyone who can reach the port can
|
||||
search, download, and read your configuration. Only combine it with a host like
|
||||
`127.0.0.1`, or keep the default key-based auth when binding to `0.0.0.0`. Put a
|
||||
TLS-terminating reverse proxy (Caddy, nginx) in front for anything internet-facing.
|
||||
|
||||
### Server modes
|
||||
|
||||
The set of routes that is actually mounted depends on how you start the server:
|
||||
|
||||
=== "Default (CDM + REST)"
|
||||
|
||||
Both the pywidevine/pyplayready CDM endpoints and the full REST API are mounted.
|
||||
This is the mode used when you run `unshackle serve` with no mode flags.
|
||||
|
||||
=== "`--api-only`"
|
||||
|
||||
Only the REST API is mounted; the CDM HTTP endpoints are omitted. Authentication
|
||||
uses the single configured API key (or none, with `--no-key`).
|
||||
|
||||
=== "`--remote-only`"
|
||||
|
||||
Only the remote-session subset of routes is exposed (health, services, search,
|
||||
and everything under `/api/session/*`). This mode implies `--api-only`, and the
|
||||
interactive Swagger UI is **not** mounted.
|
||||
|
||||
## Base URL
|
||||
|
||||
All REST endpoints live under the `/api` prefix. With the default bind address the
|
||||
base URL is:
|
||||
|
||||
```
|
||||
http://127.0.0.1:8786/api
|
||||
```
|
||||
|
||||
Every path in this documentation is relative to the host and port. For example, the
|
||||
health check is `GET http://127.0.0.1:8786/api/health`.
|
||||
|
||||
!!! tip "Interactive API docs"
|
||||
Unless you started the server with `--remote-only`, an interactive Swagger UI is
|
||||
available at [`/api/docs/`](http://127.0.0.1:8786/api/docs/). It is generated from
|
||||
the same route table the server actually serves, so it stays in sync with the
|
||||
running build. Note that in `--api-only` mode the docs page is itself behind the
|
||||
API key; only `/api/health` is exempt from authentication.
|
||||
|
||||
A quick smoke test that needs no key:
|
||||
|
||||
```shell title="Confirm the server is up"
|
||||
curl http://127.0.0.1:8786/api/health
|
||||
```
|
||||
|
||||
```json title="Response"
|
||||
{
|
||||
"status": "ok",
|
||||
"version": "5.3.0",
|
||||
"update_check": {
|
||||
"update_available": false,
|
||||
"current_version": "5.3.0",
|
||||
"latest_version": "5.3.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Endpoint map
|
||||
|
||||
Every REST path uses JSON request and response bodies and lives under `/api`. The
|
||||
table below is a map of the surface; the [Endpoints](endpoints.md) page documents each
|
||||
request and response in full.
|
||||
|
||||
### Discovery
|
||||
|
||||
| Method | Path | Purpose |
|
||||
|---|---|---|
|
||||
| `GET` | `/api/health` | Liveness and version check. Never requires a key. |
|
||||
| `GET` | `/api/services` | List the services available on this server. |
|
||||
| `POST` | `/api/search` | Run a service's search for a query. |
|
||||
| `POST` | `/api/list-titles` | List the titles behind a service title ID. |
|
||||
| `POST` | `/api/list-tracks` | List the video, audio, and subtitle tracks for a title. |
|
||||
|
||||
### Downloads and jobs
|
||||
|
||||
| Method | Path | Purpose |
|
||||
|---|---|---|
|
||||
| `POST` | `/api/download` | Queue a download; returns a `job_id`. |
|
||||
| `GET` | `/api/download/jobs` | List jobs, with filtering and sorting. |
|
||||
| `POST` | `/api/download/jobs/clear-finished` | Remove all finished jobs. |
|
||||
| `GET` | `/api/download/jobs/{job_id}` | Full detail for one job. |
|
||||
| `DELETE` | `/api/download/jobs/{job_id}` | Cancel a running job, or remove a finished one. |
|
||||
| `POST` | `/api/download/jobs/{job_id}/retry` | Re-queue a finished job's parameters as a new job. |
|
||||
| `POST` | `/api/download/jobs/{job_id}/priority` | Move a queued job to the front. |
|
||||
|
||||
### History and server info
|
||||
|
||||
| Method | Path | Purpose |
|
||||
|---|---|---|
|
||||
| `GET` | `/api/history` | Read the persisted log of finished jobs. |
|
||||
| `DELETE` | `/api/history/{job_id}` | Delete a history entry. |
|
||||
| `GET` | `/api/profiles` | Named credential profiles per service. |
|
||||
| `GET` | `/api/config` | The server's effective, redacted configuration. |
|
||||
| `GET` | `/api/env/check` | Presence and versions of external tools. |
|
||||
|
||||
### Maintenance
|
||||
|
||||
| Method | Path | Purpose |
|
||||
|---|---|---|
|
||||
| `POST` | `/api/maintenance/clear-cache` | Clear the cache directory. |
|
||||
| `POST` | `/api/maintenance/clear-temp` | Clear the temp directory. |
|
||||
| `POST` | `/api/maintenance/refresh-services` | `git pull` each configured service repository. |
|
||||
|
||||
### Remote-download sessions
|
||||
|
||||
| Method | Path | Purpose |
|
||||
|---|---|---|
|
||||
| `POST` | `/api/session/create` | Start a server-side, authenticated service session. |
|
||||
| `GET` | `/api/session/{session_id}` | Session info and time-to-live. |
|
||||
| `DELETE` | `/api/session/{session_id}` | Tear down a session. |
|
||||
| `GET` | `/api/session/{session_id}/titles` | Titles for the session's title ID. |
|
||||
| `POST` | `/api/session/{session_id}/tracks` | Tracks (with URLs) for a chosen title. |
|
||||
| `POST` | `/api/session/{session_id}/segments` | Per-track segment/download details. |
|
||||
| `POST` | `/api/session/{session_id}/license` | Proxy or server-side DRM licensing. |
|
||||
| `GET` | `/api/session/{session_id}/prompt` | Poll for interactive auth status/prompt. |
|
||||
| `POST` | `/api/session/{session_id}/prompt` | Submit an answer to an auth prompt. |
|
||||
|
||||
!!! note "Remote-only routes"
|
||||
The health, services, search, and `/api/session/*` routes are the ones exposed
|
||||
when the server runs with `--remote-only`. Everything else (downloads, jobs,
|
||||
history, config, maintenance) is only available in the full or `--api-only` modes.
|
||||
|
||||
## Authentication in one line
|
||||
|
||||
With the default configuration, send your API secret in the `X-Secret-Key` header on
|
||||
every request except `/api/health`:
|
||||
|
||||
```shell title="An authenticated request"
|
||||
curl -X POST http://127.0.0.1:8786/api/search \
|
||||
-H "X-Secret-Key: your-api-secret" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"service": "NF", "query": "example"}'
|
||||
```
|
||||
|
||||
A missing or unknown key returns `401`. The full model, including per-key service
|
||||
allowlists, is covered in [Authentication](authentication.md).
|
||||
|
||||
## Where to go next
|
||||
|
||||
<div class="grid cards" markdown>
|
||||
|
||||
- **[Quick Start](quickstart.md)**: start the server, set a key, and run your first
|
||||
end-to-end download over the API.
|
||||
- **[Authentication](authentication.md)**: the `X-Secret-Key` header, `--no-key`,
|
||||
per-key service allowlists, and CORS.
|
||||
- **[Endpoints](endpoints.md)**: every request body, query parameter, and response
|
||||
shape, endpoint by endpoint.
|
||||
- **[Job Lifecycle](job-lifecycle.md)**: how a download moves from `queued` to a
|
||||
terminal state, live progress, cancellation, and retries.
|
||||
- **[Remote Sessions](remote-sessions.md)**: the `/api/session/*` flow for driving a
|
||||
service from a thin remote client.
|
||||
- **[Error Responses](errors.md)**: the standard error envelope, error codes, and
|
||||
their HTTP statuses.
|
||||
|
||||
</div>
|
||||
Reference in New Issue
Block a user