Skip to content

Contract: Servarr download-client registration

Status: Accepted

How lemonfiber registers a download client — SABnzbd or qBittorrent — into a Servarr application during seed. The Servarr apps read this shape; lemonfiber writes it.

Satisfies: D1-R4, D1-R8, D1-R11


A working *arr needs each download client registered, and the registration is not a flat set of keys. Servarr carries a client’s connection settings as a fields array whose entries differ by implementation, keyed by an implementation name and a configContract — so “register SABnzbd in Sonarr” is a specific document, not a host and a port.

The field set is stable for a pinned Servarr version, and the stack pins its versions. So lemonfiber writes the fields directly rather than discovering them at runtime; when a stack upgrade moves a field, this contract and the writer move with it in the same change. Recording the shape here is what makes that a review rather than a surprise.

A POST to /api/v3/downloadclient on the target Servarr application, JSON:

{
"enable": true,
"protocol": "usenet",
"name": "SABnzbd",
"implementation": "Sabnzbd",
"configContract": "SabnzbdSettings",
"fields": [
{ "name": "host", "value": "sabnzbd" },
{ "name": "port", "value": 8080 },
{ "name": "apiKey", "value": "<read from the client's own config>" },
{ "name": "tvCategory", "value": "tv" }
]
}

protocol is usenet for SABnzbd and torrent for qBittorrent. name is what the operator sees in the service’s own interface. implementation and configContract select the field schema and are not interchangeable.

The fields lemonfiber sets, per implementation

Section titled “The fields lemonfiber sets, per implementation”

Only the fields that make a working connection are written; the rest keep the service’s own defaults.

Implementation implementation configContract Connection fields Credential fields
SABnzbd Sabnzbd SabnzbdSettings host, port apiKey
qBittorrent QBittorrent QBittorrentSettings host, port username, password

The credential is the client’s own, obtained the way that client provides it: SABnzbd’s apiKey is read from its sabnzbd.ini (D1-R1); qBittorrent has no durable key, so its username/password is the web UI password lemonfiber generates and sets (D1-R16).

The category field is named per application

Section titled “The category field is named per application”

The category tags a download so the application that requested it can find its own completed items and no others. Its field name is not shared — each Servarr application names it after the media it manages:

Application Category field
Sonarr tvCategory
Radarr movieCategory
Lidarr musicCategory

So the same download client is registered into Sonarr with tvCategory and into Radarr with movieCategory, each carrying that application’s category value. A registration built for the wrong application names a field the target does not have.

After writing, the client list is read back from the same endpoint and each entry’s host and port are recovered from its fields. An existing client is matched by that endpoint rather than by its name, so a client an operator renamed is recognised as the same connection and not duplicated (D1-R8). A refusal carries the application’s own words rather than a paraphrase (D1-R11).

This page lives in another repository Rendered from lemonfiber/spec at 1d10402, 2026-09-09. Read the source of this page