Ctrl K
ComunidadGuías…

docs/CUSTOM_PROVIDER_API.md

Rama master · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# Custom HTTP/JSON Provider

The `customapi` provider turns any HTTP endpoint that returns JSON into a
subtitle source — **without writing a plugin**. Point it at a private
subtitle server that implements the small contract below, or adapt an
existing third-party REST API using the mapping settings.

Because it only sends configured HTTP requests and never executes
third-party code, it is the safest way to integrate a custom source.
For anything the mapping can't express (multi-step flows, login sessions,
HTML scraping), write a [plugin](https://sublarr.de/docs/development/plugin-development/) instead.

## Quick start (private server)

1. Implement the three endpoints below on your server.
2. In Sublarr: **Settings → Providers → customapi**, set the **Base URL**
   (e.g. `http://192.168.1.10:9000`) and optionally an **API Key**.
3. Done — results are scored, cached, rate-limited, and circuit-broken
   exactly like every built-in provider.

## The contract

All endpoints are relative to the configured base URL. Paths are
configurable (`Search Path`, `Download Path`); the defaults are shown.

### `GET /search`

Sublarr sends one request per search with the video's metadata as query
parameters. All parameters are optional — use what you need:

| Parameter | Example | Notes |
|---|---|---|
| `title` | `Inception` | Movies only |
| `series_title` | `Frieren` | Episodes only |
| `season` | `1` | Episodes only |
| `episode` | `4` | Episodes only |
| `year` | `2010` | |
| `imdb_id` | `tt1375666` | |
| `tmdb_id` | `27205` | |
| `tvdb_id` | `424536` | |
| `anilist_id` | `154587` | |
| `languages` | `de,en` | Comma-separated ISO 639-1 codes |
| `file_hash` | `8e245d9679d31e12` | OpenSubtitles-style hash |
| `file_size` | `3841923072` | Bytes |
| `release_group` | `SubsPlease` | |
| `resolution` | `1080p` | |
| `source` | `WEB-DL` | |

Respond with `200` and:

```json
{
  "results": [
    {
      "id": "abc123",
      "language": "de",
      "download_url": "/download/abc123",
      "filename": "Frieren.S01E04.de.ass",
      "format": "ass",
      "release": "SubsPlease 1080p",
      "hearing_impaired": false,
      "forced": false,
      "matches": ["series", "season", "episode", "release_group"]
    }
  ]
}
```

Per-item fields:

| Field | Required | Notes |
|---|---|---|
| `id` | ✅ | Unique subtitle id (string or number) |
| `language` | recommended | ISO 639-1. Falls back to the (single) requested language; items whose language doesn't match the request are dropped |
| `download_url` | — | Absolute or relative to the base URL. Omit it to have Sublarr use the download path (`/download/{id}`) |
| `filename` | recommended | Used for format detection |
| `format` | — | `ass` / `ssa` / `srt` / `vtt`; inferred from `filename` when omitted |
| `release` | — | Release/version info shown in the UI |
| `hearing_impaired` | — | Boolean |
| `forced` | — | Boolean |
| `matches` | — | Which query attributes this subtitle matches — this is what drives scoring. Valid values include `hash`, `series`, `title`, `year`, `season`, `episode`, `release_group`, `source`, `resolution`, `video_codec` |

Auth failures should return `401`/`403`; rate limiting `429` (a
`Retry-After` header is honored).

### `GET /download/{id}`

Returns the raw subtitle file (`.ass`/`.srt`/…) or a ZIP archive
containing it (ASS/SSA is preferred when extracting).

### `GET /health` *(optional)*

Return `200` when healthy. Without this endpoint, any non-5xx response
from the base URL counts as healthy.

### Authentication

If an API key is configured, it is sent on every request in the
`X-API-Key` header (configurable). When the header is set to
`Authorization` and the key contains no scheme, `Bearer ` is prefixed
automatically.

## Adapting an existing API

Three settings map a foreign response shape onto the contract:

- **Results Path** — dot-notation path to the result array inside the
  response, e.g. `data.subtitles`. Leave empty for a top-level array.
- **Field Map** (JSON) — maps Sublarr fields to per-item paths
  (dot-notation supported):

  ```json
  {"subtitle_id": "attributes.sid", "download_url": "attributes.file.url", "release_info": "attributes.release"}
  ```

  Mappable fields: `subtitle_id`, `language`, `download_url`, `filename`,
  `format`, `release_info`, `hearing_impaired`, `forced`, `matches`.
- **Extra Query Params** (JSON) — static parameters added to every search
  request, e.g. `{"apikey": "...", "type": "subtitle"}`.

## Multiple instances

Several independent servers can be configured via
**Extra Instances (JSON array)** on the `customapi` provider:

```json
[
  {"name": "Home NAS", "base_url": "http://192.168.1.10:9000", "api_key": "s3cret"},
  {"name": "VPS Mirror", "base_url": "https://subs.example.org", "search_path": "/api/search"}
]
```

Each entry is registered as its own provider named `customapi-<name>`
(e.g. `customapi-home-nas`) with separate statistics, health state,
circuit breaker, and priority. Instance entries accept the same keys as
the main provider settings (without the `customapi_` prefix): `base_url`,
`api_key`, `api_key_header`, `search_path`, `download_path`,
`results_path`, `field_map` (object), `extra_params` (object).

## Security notes

- Only `http`/`https` URLs are accepted. Private LAN addresses are
  allowed (that's the point), but cloud-metadata endpoints and link-local
  addresses are always blocked.
- Downloads are streamed with a 50 MB cap and validated as subtitle
  content before being saved.
- The API key is encrypted at rest like all other provider credentials.