Zum Inhalt springen
nexcrate
API

Ein fester Vertrag für andere Programme

Nexview, nexbeat und nexdeck sprechen mit nexcrate über dieselbe Schnittstelle, die auch dir offensteht: /api/v1. Sie bleibt, wie sie ist, während sich die Seiten der Oberfläche weiterentwickeln. Diese Seite erklärt, wie man hineinkommt, und listet darunter jede Adresse.

Stand der Referenz: nexcrate 0.2.0, Vertrag v1, Stufe V5, 43 Adressen. Sie wird aus nexcrates Code erzeugt; die Beschreibungen der einzelnen Adressen stehen deshalb auf Englisch, so wie im Code.

Zwei Schnittstellen

Die Oberfläche von nexcrate benutzt selbst eine Schnittstelle unter /api, mit dem Anmelde-Cookie. Die folgt den Seiten der Oberfläche und ändert sich mit ihnen. Andere Programme nehmen /api/v1 und sonst nichts.

  • /api/v1 öffnet sich nur mit einem Schlüssel, nie mit dem Cookie der Oberfläche.
  • Was sich ändert, braucht dort keinen Kopf X-Requested-With.
  • Indexer, Download-Programme, Profile, das Konto und abgelegte Geheimnisse erreicht kein Schlüssel. Für sie gibt es unter /api/v1 keine Adresse.

Jede laufende nexcrate beschreibt sich selbst: /api/openapi.json ist das OpenAPI-Dokument, /api/docs die Seite dazu.

Schlüssel und Umfänge

Unter Einstellungen › System › API-Schlüssel auf Neuer Schlüssel. Gib jedem Programm einen eigenen, dann lässt sich einer widerrufen, ohne die anderen zu stören. Der Schlüssel wird genau einmal gezeigt; nexcrate behält nur seinen Fingerabdruck.

Der Dialog Neuer Schlüssel mit Name und den drei Umfängen Lesen, Anfragen und Bedienen
UmfangWas er darf
LesenBibliothek, Fassungen, Zustände, Speicher, Gesundheit, Warteschlange, Probleme, Verlauf, Kalender, Wertungen und Ereignisse lesen. Jeder Schlüssel hat ihn.
AnfragenTitel anfragen und nachfordern, überwachen oder einfrieren, suchen lassen, zurücknehmen und Dateien in den Papierkorb legen.
BedienenHängende Downloads noch einmal versuchen, entfernen oder neu suchen lassen, einen Pfad bestätigen und Dateien von Hand zuordnen.

Gesendet wird der Schlüssel im Kopf, nie in der Adresse:

HTTP
Authorization: Bearer nxc_…

Koppeln

Ein Programm kann um einen Schlüssel bitten, statt dass jemand ihn abtippt. So verbinden sich Nexview, nexbeat und nexdeck. Die beiden Adressen dafür sind die einzigen unter /api/v1, die keinen Schlüssel brauchen.

  1. BittenPOST /api/v1/pairing mit dem Namen des Programms und den gewünschten Umfängen. Die Antwort trägt eine pairing_id, ein secret und einen kurzen code. Das Programm zeigt den Code an.
  2. BestätigenIn nexcrate steht die Bitte oben auf jeder Seite und unter Einstellungen › System › API-Schlüssel bei Programme, die sich verbinden wollen. Der Besitzer vergleicht den Code und klickt Verbinden oder Ablehnen; er darf weniger Umfänge geben als erbeten.
  3. AbholenDas Programm fragt GET /api/v1/pairing/{pairing_id} mit dem Kopf X-Pairing-Secret, im Abstand von poll_seconds. Die erste Antwort mit confirmed trägt den Schlüssel, genau einmal.
Terminal
curl -s -X POST http://nexcrate:8390/api/v1/pairing \
  -H 'Content-Type: application/json' \
  -d '{"app": "Mein Skript", "scopes": ["read", "request"]}'

Die erste Anfrage

Welche Fassungen es gibt und ob sie bereit sind:

Terminal
curl -s http://nexcrate:8390/api/v1/versions \
  -H "Authorization: Bearer $NEXCRATE_KEY"

Einen Film in einer Fassung anfragen und gleich suchen lassen. Zweimal fragen ergibt dasselbe, nie ein Doppel; origin ist deine eigene Kennung und kommt am Titel zurück:

Terminal
curl -s -X POST http://nexcrate:8390/api/v1/requests \
  -H "Authorization: Bearer $NEXCRATE_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"kind": "movie", "ref": "tmdb:28503", "versions": ["<id der Fassung>"],
       "search_now": true, "origin": "mein-skript:1"}'

Regeln der Antworten

  • Ein Titel ist kind plus ref. ref nennt seine Quelle: tmdb:, imdb:, bei Serien auch tvdb:, bei Musik mbid:. Was nur eine Art betrifft, steht unter einem Schlüssel mit ihrem Namen.
  • Ein Feld fehlt nie. Ist ein Wert unbekannt, steht null da.
  • Fehler sind flach: {"code": "…", "message": "…", "params": {…}}. Der code ist fest, die message ein englischer Ersatztext. Jede Adresse nennt in der Referenz ihre Fehlercodes.
  • Jede Antwort trägt X-Request-Id. Ein Programm darf eine eigene mitschicken; nexcrate schreibt sie in jede Protokollzeile dieser Anfrage.
  • Je Schlüssel gibt es eine Obergrenze für Anfragen in der Sekunde. Wer sie überschreitet, bekommt 429 mit Retry-After.
  • Stabil heißt: Der Vertrag ändert seine Hauptnummer nur mit einem Bruch, und die steht in der Adresse. GET /api/v1/system nennt Hauptnummer und Stufe; eine höhere Stufe bringt nur Neues dazu.

Ereignisse und Webhooks

Was in nexcrate passiert, hat eine Laufnummer. GET /api/v1/events?after=… liefert, was seit einer Nummer kam, und next_after für die nächste Frage. GET /api/v1/events/stream liefert dasselbe als Server-Sent Events. Die Bibliothek selbst lässt sich genauso lesen: GET /api/v1/titles?after=… gibt nur, was sich geändert hat.

Webhooks schickt nexcrate an Adressen, die der Besitzer unter Einstellungen › System › Webhooks einträgt; kein Schlüssel reicht dorthin. Jede Zustellung trägt X-Nexcrate-Event, X-Nexcrate-Delivery und eine Unterschrift:

HTTP
X-Nexcrate-Signature: t=<Unix-Zeit>,v1=<HMAC-SHA256 über "<t>.<Rumpf>">

Geprüft wird mit dem Geheimnis des Ziels über den rohen Rumpf, so wie er ankam:

Python
import hashlib, hmac

def echt(geheimnis: str, kopf: str, rumpf: bytes) -> bool:
    teile = dict(stueck.split("=", 1) for stueck in kopf.split(","))
    erwartet = hmac.new(geheimnis.encode(), teile["t"].encode() + b"." + rumpf,
                        hashlib.sha256).hexdigest()
    return hmac.compare_digest(erwartet, teile["v1"])

Scheitert eine Zustellung, versucht nexcrate es nach 1, 5, 30 und 120 Minuten wieder. Ein neues Ziel beginnt beim neuesten Ereignis, nicht mit allem, was vorher war.

Referenz

System und Fassungen

Wer antwortet, welche Fassungen es gibt, wie viel Platz dahinter frei ist und was gerade nicht stimmt.

GET/api/v1/healthWhat is wrong with this nexcrateLesen

Findings from what nexcrate already knows: asking sends no request anywhere and wakes no disk. Translate by code; params carry the names.

Antwort 200 HealthOut

FeldTypBedeutung
items *array of FindingOutThe worst first; empty when nothing is wrong.

Fehlercodes

  • 401 api_key_missing, api_key_invalid
  • 403 scope_missing
  • 500 internal_error
GET/api/v1/statesThe states a version, a season or an episode can haveLesen

The list is part of the contract. A later stage may add a state; a program shows one it does not know as unknown instead of failing.

Antwort 200 StatesOut

FeldTypBedeutung
items *array of StateOutIn the order of precedence: the first that applies wins.

Fehlercodes

  • 401 api_key_missing, api_key_invalid
  • 403 scope_missing
  • 500 internal_error
GET/api/v1/storageFree space behind every versionLesen

Free and total space of the disk each version's folder lies on. Never a path.

Antwort 200 StorageListOut

FeldTypBedeutung
items *array of StorageOut

Fehlercodes

  • 401 api_key_missing, api_key_invalid
  • 403 scope_missing
  • 500 internal_error
GET/api/v1/systemWhat this nexcrate is and can doLesen

The version, the stage of the contract, what works per kind, and the fixed id of the installation. Ask this first: a program that needs more than this nexcrate carries can say so instead of failing.

Antwort 200 SystemOut

FeldTypBedeutung
app *string
version *stringThe running nexcrate.
contract *Contract
installation_id *stringFixed for this installation, whatever address it answers at. Tells a moved nexcrate from another.
scopes *array of stringWhat the key of this request may do.
capabilities *Capabilities
web_url *string | nullThe address the owner gave for reaching nexcrate, sub path included; null without one.
links *object of stringThe jumps into nexcrate's pages, to put behind web_url (or the address you reach nexcrate at): title, version, profile, download, problems, recycle_bin, calendar. They stay whatever the pages are called.
update *app__routers__v1__UpdateOut

Fehlercodes

  • 401 api_key_missing, api_key_invalid
  • 403 scope_missing
  • 500 internal_error
GET/api/v1/versionsList the versions and whether they are readyLesen

A version is a named slot per kind, such as HD and 4K for movies. A version that is not ready does nothing by itself: offer only ready ones, and tell the owner the reasons of the others.

Parameter

FeldWoTypBedeutung
kindquerystring | null

Antwort 200 VersionsOut

FeldTypBedeutung
items *array of VersionOutPer kind none, one or several: assume no number.

Fehlercodes

  • 401 api_key_missing, api_key_invalid
  • 403 scope_missing
  • 422 kind_unsupported, invalid_input
  • 500 internal_error
Referenz

Titel lesen

Die Bibliothek als Ganzes oder als Änderung seit einer Marke, ein Titel mit Staffeln und Folgen, sein Verlauf und warum etwas noch fehlt.

GET/api/v1/titlesThe library, whole or what changed since a numberLesen

With after=0 the whole library in pages; afterwards ask with the next_after of the last answer and get only what changed since, and what went away. A title's number moves whenever anything of what this list says about it changes, some seconds after the change. A series carries its seasons; episodes are not in the list: fetch the season when its number moved. marker_too_old: the number is older than 90 days of removals, start over at 0.

Parameter

FeldWoTypBedeutung
afterqueryintegerThe next_after of the last answer; 0 for everything.
kindquerystring | null
limitqueryinteger

Antwort 200 TitlesOut

FeldTypBedeutung
items *array of ChangedTitleOutTitles that are new or changed, the oldest change first.
removed *array of RemovedOutTitles that went away. Never part of a fetch from 0.
next_after *integerAsk with this next.
more *booleanTrue: ask again at once, there is more.
latest *integerThe highest number given so far.

Fehlercodes

  • 401 api_key_missing, api_key_invalid
  • 403 scope_missing
  • 410 marker_too_old
  • 422 kind_unsupported, invalid_input
  • 500 internal_error
POST/api/v1/titles/lookupLook up many titles at onceLesen

Up to 100 titles in one call, for a page of tiles that each need a badge. Answers in the order asked, straight from the library and without the delay of the change numbers. An entry nexcrate cannot answer carries error; the batch never fails for one entry.

Anfrage LookupIn

FeldTypBedeutung
items *array of LookupItemIn

Antwort 200 LookupOut

FeldTypBedeutung
items *array of LookupItemOutIn the order asked.

Fehlercodes

  • 401 api_key_missing, api_key_invalid
  • 403 scope_missing
  • 422 invalid_input
  • 500 internal_error
GET/api/v1/titles/series/{ref}/seasons/{season}The episodes of one seasonLesen

Every episode TMDB lists for the season, in TMDB's numbers, with every version's state, size and quality. Season 0 holds the specials.

Parameter

FeldWoTypBedeutung
ref *pathstring
season *pathinteger

Antwort 200 SeasonDetailOut

FeldTypBedeutung
season *integer
name *string | null
episodes *array of app__routers__v1__EpisodeOut

Fehlercodes

  • 401 api_key_missing, api_key_invalid
  • 403 scope_missing
  • 404 title_not_found, season_not_found
  • 409 ref_ambiguous
  • 422 ref_invalid, ref_source_unknown, invalid_input
  • 500 internal_error
POST/api/v1/titles/whyWhy many titles are not there yetLesen

The same for up to 50 titles, in the order asked; an entry nexcrate cannot answer carries error and breaks nothing else.

Anfrage WhyManyIn

FeldTypBedeutung
items *array of WhyItemIn

Antwort 200 WhyManyOut

FeldTypBedeutung
items *array of WhyManyItemOutIn the order asked.

Fehlercodes

  • 401 api_key_missing, api_key_invalid
  • 403 scope_missing
  • 422 invalid_input
  • 500 internal_error
GET/api/v1/titles/{kind}/{ref}One title, a series with its seasonsLesen

The title as the list shows it; a series also with every season and, per version, its state, numbers and size on disk. ref takes every source nexcrate knows for the kind: tmdb and imdb, for a series also tvdb.

Parameter

FeldWoTypBedeutung
kind *pathstring
ref *pathstring

Fehlercodes

  • 401 api_key_missing, api_key_invalid
  • 403 scope_missing
  • 404 title_not_found
  • 409 ref_ambiguous
  • 422 kind_unsupported, ref_invalid, ref_source_unknown, invalid_input
  • 500 internal_error
GET/api/v1/titles/{kind}/{ref}/historyThe history of a titleLesen

Loaded, filed (with the replaced file's quality and size), failed, deleted, restored, requested, taken back, and what programs did, newest first in pages.

Parameter

FeldWoTypBedeutung
kind *pathstring
ref *pathstring
beforequeryinteger | nullThe next_before of the last page.
limitqueryinteger

Antwort 200 HistoryOut

FeldTypBedeutung
items *array of HistoryItemOutNewest first. Entries from before V3 carry only kind and time.
next_before *integer | nullAsk with before set to this for older entries; null at the end.

Fehlercodes

  • 401 api_key_missing, api_key_invalid
  • 403 scope_missing
  • 404 title_not_found
  • 409 ref_ambiguous
  • 422 kind_unsupported, ref_invalid, ref_source_unknown, invalid_input
  • 500 internal_error
GET/api/v1/titles/{kind}/{ref}/whyWhy a title is not there yetLesen

Per version one reason as a code with params, the weightiest first: loading, stuck, not released yet, the last search found only releases the profile refuses, the next search, waiting out a delay. Build the sentence from the code. Asks no indexer.

Parameter

FeldWoTypBedeutung
kind *pathstring
ref *pathstring

Fehlercodes

  • 401 api_key_missing, api_key_invalid
  • 403 scope_missing
  • 404 title_not_found
  • 409 ref_ambiguous
  • 422 kind_unsupported, ref_invalid, ref_source_unknown, invalid_input
  • 500 internal_error
Referenz

Anfragen und zurücknehmen

Einen Titel anfragen oder mehr davon, vorher fragen, was es gäbe, einfrieren, suchen lassen, zurücknehmen und entfernen.

POST/api/v1/previewAsk before a requestAnfragen

Whether the title is there, when it comes out, whether each version would search and load by itself, and with search a search of the indexers without loading (follow it with GET /api/v1/preview/{preview_id}). A title nexcrate does not have comes from TMDB; a series nexcrate does not have cannot be searched yet.

Anfrage app__routers__v1_round__PreviewIn

FeldTypBedeutung
kind *string
ref *stringA title nexcrate does not have only by tmdb:.
versionsarray of string | nullFixed version ids; left out, every version of the kind.
searchbooleanAlso search the indexers, without loading, within their budget.
seriesPreviewSeriesIn | null

Fehlercodes

  • 401 api_key_missing, api_key_invalid
  • 403 scope_missing
  • 409 ref_ambiguous, search_busy, tmdb_not_configured, tmdb_token_unreadable
  • 422 kind_unsupported, ref_invalid, ref_source_unknown, ref_not_addable, version_unknown, scope_not_for_kind, invalid_input
  • 500 internal_error
  • 502 tmdb_token_rejected, tmdb_rate_limited, tmdb_unavailable, tmdb_unreachable, tmdb_http_error
  • 504 tmdb_timeout
GET/api/v1/preview/{preview_id}What a preview's search foundAnfragen

Per version the release nexcrate would take, or why nothing fits. Kept 30 minutes.

Parameter

FeldWoTypBedeutung
preview_id *pathstring

Antwort 200 PreviewResultOut

FeldTypBedeutung
preview_id *string
state *stringrunning or done.
releases *integerReleases of the title found.
indexers *array of PreviewIndexerOut
versions *array of PreviewResultVersionOut

Fehlercodes

  • 401 api_key_missing, api_key_invalid
  • 403 scope_missing
  • 404 preview_not_found
  • 422 invalid_input
  • 500 internal_error
POST/api/v1/requestsRequest a title, or request more of itAnfragen

One call for both: a title nexcrate lacks is added from TMDB, versions it lacks are added, and the seasons and episodes under series are switched on. Asking twice gives the same, never a double. Requesting more never switches anything off, and what the owner switched by hand stays. A version a Radarr or Sonarr connection feeds answers 409. search_now puts the title into the order of the automatic, even with its switch off, within the indexers' budget. 200 when the title was there, 201 when it came with this call.

Anfrage RequestIn

FeldTypBedeutung
kind *string
ref *stringA new title only by tmdb:, a new album or artist by mbid: (its release group or artist).
versionsarray of string | nullFixed version ids. Needed for a movie or series; an album takes the one music version without it, an artist has none.
seriesSeriesScopeIn | nullOnly for a series; a movie answers 422.
artistArtistScopeIn | nullOnly for an artist: which albums to watch.
search_nowbooleanSearch as soon as the order of the automatic allows.
originstring | nullThe program's own reference, at most 100 printable characters; listed back with the title and its versions.

Antwort 200 RequestOut

FeldTypBedeutung
created *booleanTrue when the title came in with this request.
versions *array of RequestedVersionOut
albums_watchedinteger | nullAn artist: how many of its albums this request watched; null otherwise.
search *stringqueued, not_asked, nothing_wanted, or not_possible (an anime series while capabilities.anime is false; the note anime_not_supported says it).
notes *array of app__routers__v1_write__NoteOut
title *TitleOut

Fehlercodes

  • 401 api_key_missing, api_key_invalid
  • 403 scope_missing
  • 404 title_not_found, version_not_found
  • 409 ref_ambiguous, version_fed_by_source, tmdb_not_configured, tmdb_token_unreadable
  • 422 kind_unsupported, ref_invalid, ref_source_unknown, version_unknown, version_kind_mismatch, scope_not_for_kind, season_not_found, episode_not_found, track_not_found, ref_not_addable, invalid_input
  • 500 internal_error
  • 502 tmdb_token_rejected, tmdb_rate_limited, tmdb_unavailable, tmdb_unreachable, tmdb_http_error
  • 504 tmdb_timeout
DELETE/api/v1/titles/{kind}/{ref}Remove a title from the libraryAnfragen

As the button in nexcrate: nexcrate's own versions go, and the title when none is left. Its running downloads are stopped at their client first. With delete_files the files go into the recycle bin before; ⚠️ a title that is gone cannot take them back, so add it again first. Versions a Radarr or Sonarr connection feeds stay, and the answer is 409 title_has_source_versions.

Parameter

FeldWoTypBedeutung
kind *pathstring
ref *pathstring
delete_filesquerybooleanMove the files into the recycle bin first.

Fehlercodes

  • 401 api_key_missing, api_key_invalid
  • 403 scope_missing
  • 404 title_not_found
  • 409 ref_ambiguous, download_finished, title_has_source_versions
  • 422 kind_unsupported, ref_invalid, ref_source_unknown, invalid_input
  • 500 internal_error
POST/api/v1/titles/{kind}/{ref}/delete-filesMove files into the recycle binAnfragen

The files of the scope go into the recycle bin with their subtitles; they come back with POST /api/v1/recycle-bin/{entry_id}/restore until the bin's time is up. A file of a series that holds several episodes goes whole when one of them is named.

Parameter

FeldWoTypBedeutung
kind *pathstring
ref *pathstring

Anfrage app__routers__v1_write__DeleteFilesIn

FeldTypBedeutung
versionsarray of string | nullFixed version ids (v_…); without it every version of nexcrate's own.
seriesSeriesScopeIn | null
albumAlbumScopeIn | nullOnly for an album: single tracks.

Antwort 200 DeleteFilesOut

FeldTypBedeutung
versions *array of DeletedVersionOut

Fehlercodes

  • 401 api_key_missing, api_key_invalid
  • 403 scope_missing
  • 404 title_not_found, version_not_found
  • 409 ref_ambiguous, version_fed_by_source, download_importing
  • 422 kind_unsupported, ref_invalid, ref_source_unknown, version_unknown, version_kind_mismatch, scope_not_for_kind, season_not_found, episode_not_found, track_not_found, invalid_input
  • 500 internal_error
PUT/api/v1/titles/{kind}/{ref}/monitoringFreeze or thawAnfragen

Only the switches: no download stops, no file moves. Freezing a whole series also keeps seasons TMDB names later out; thawing it takes them in again.

Parameter

FeldWoTypBedeutung
kind *pathstring
ref *pathstring

Anfrage MonitoringIn

FeldTypBedeutung
monitored *booleanFalse freezes: nothing is searched or upgraded, files stay. True thaws. An artist frozen is Lidarr's unmonitored artist: none of its albums is searched on its own, their switches stay.
versionsarray of string | nullFixed version ids (v_…); without it every version of nexcrate's own.
seriesSeriesScopeIn | null
artistArtistMonitoringIn | null

Antwort 200 MonitoringOut

FeldTypBedeutung
versions *array of MonitoredVersionOut
title *TitleOut

Fehlercodes

  • 401 api_key_missing, api_key_invalid
  • 403 scope_missing
  • 404 title_not_found, version_not_found
  • 409 ref_ambiguous, version_fed_by_source
  • 422 kind_unsupported, ref_invalid, ref_source_unknown, version_unknown, version_kind_mismatch, scope_not_for_kind, season_not_found, episode_not_found, track_not_found, invalid_input
  • 500 internal_error
POST/api/v1/titles/{kind}/{ref}/searchAsk for a searchAnfragen

The title goes into the order of the automatic, right after the replacements, even with its switch off, and within the indexers' budget: a hundred asks at once are searched one after the other.

Parameter

FeldWoTypBedeutung
kind *pathstring
ref *pathstring

Antwort 202 app__routers__v1_write__SearchOut

FeldTypBedeutung
search *stringqueued, running (a search of it runs already), nothing_wanted, or not_possible (an anime series while capabilities.anime is false).

Fehlercodes

  • 401 api_key_missing, api_key_invalid
  • 403 scope_missing
  • 404 title_not_found
  • 409 ref_ambiguous
  • 422 kind_unsupported, ref_invalid, ref_source_unknown, invalid_input
  • 500 internal_error
POST/api/v1/titles/{kind}/{ref}/withdrawTake a request backAnfragen

Watching off for the scope, running downloads that lie wholly in it stopped at their client (never blocklisted), and with delete_files the files moved into the recycle bin. A download being filed away cannot be stopped: then 409 download_finished and nothing changed. A title or version a program brought and that is empty afterwards goes.

Parameter

FeldWoTypBedeutung
kind *pathstring
ref *pathstring

Anfrage WithdrawIn

FeldTypBedeutung
versionsarray of string | nullFixed version ids (v_…); without it every version of nexcrate's own.
seriesSeriesScopeIn | null
delete_filesbooleanAlso move the files of the scope into the recycle bin.

Antwort 200 WithdrawOut

FeldTypBedeutung
title_removed *booleanA title a program added goes when nothing of it is watched and no file is left. An album stays in its artist's catalogue; an artist a program added goes when none of its albums is left.
versions *array of WithdrawnVersionOut
albumsarray of WithdrawnAlbumOut | nullAn artist: what happened per album.

Fehlercodes

  • 401 api_key_missing, api_key_invalid
  • 403 scope_missing
  • 404 title_not_found, version_not_found
  • 409 ref_ambiguous, version_fed_by_source, download_finished, download_importing
  • 422 kind_unsupported, ref_invalid, ref_source_unknown, version_unknown, version_kind_mismatch, scope_not_for_kind, season_not_found, episode_not_found, track_not_found, invalid_input
  • 500 internal_error
Referenz

Downloads

Was lädt, was hängt, was gescheitert ist, und was ein Programm daran tun darf.

POST/api/v1/downloads/{download_id}/assignAssign the files of a download by handBedienen

A series: each file with its episodes in TMDB's numbers, filed in the background; a file with no episodes is not filed, a file left out keeps its decision. A movie with several videos: exactly one file, the one to file. Replacing a file that is not worse needs confirm: ["not_better"].

Parameter

FeldWoTypBedeutung
download_id *pathinteger

Anfrage app__routers__v1_back__AssignIn

FeldTypBedeutung
files *array of AssignFileIn
albumAssignAlbumIn | nullOnly for an album download.
confirmarray of "not_better"Replace a file that is not worse all the same, as the owner may.

Antwort 200 ActOut

FeldTypBedeutung
download *QueueItemOutThe download as it stands after the action.

Fehlercodes

  • 401 api_key_missing, api_key_invalid
  • 403 scope_missing
  • 404 download_not_found
  • 409 action_not_allowed, download_not_assignable, download_busy, assignment_not_better, assignment_covers_more, download_files_changed, download_not_choosable
  • 422 episode_not_found, episode_twice, scope_not_for_kind, invalid_input, track_not_found, release_not_of_album, track_not_in_release, track_twice, release_fixed
  • 500 internal_error
POST/api/v1/downloads/{download_id}/clearTake a failed download off the problemsBedienen

It stays in the history, and its release stays on the blocklist.

Parameter

FeldWoTypBedeutung
download_id *pathinteger

Antwort 200 ActOut

FeldTypBedeutung
download *QueueItemOutThe download as it stands after the action.

Fehlercodes

  • 401 api_key_missing, api_key_invalid
  • 403 scope_missing
  • 404 download_not_found
  • 409 action_not_allowed, download_not_failed
  • 422 invalid_input
  • 500 internal_error
POST/api/v1/downloads/{download_id}/confirm-mappingConfirm the proposed path of a downloadBedienen

Stores the proposal of path_not_found with the download client and files the download away again.

Parameter

FeldWoTypBedeutung
download_id *pathinteger

Antwort 200 ActOut

FeldTypBedeutung
download *QueueItemOutThe download as it stands after the action.

Fehlercodes

  • 401 api_key_missing, api_key_invalid
  • 403 scope_missing
  • 404 download_not_found
  • 409 action_not_allowed, mapping_not_proposed
  • 422 invalid_input
  • 500 internal_error
GET/api/v1/downloads/{download_id}/filesThe files of a stuck downloadLesen

Every video with what nexcrate read from its name and decided; for a series every episode in TMDB's numbers with the file the version holds for it. name is relative to the download, never a path of the disk.

Parameter

FeldWoTypBedeutung
download_id *pathinteger

Fehlercodes

  • 401 api_key_missing, api_key_invalid
  • 403 scope_missing
  • 404 download_not_found
  • 422 invalid_input
  • 500 internal_error
POST/api/v1/downloads/{download_id}/finishFile nothing more of a downloadBedienen

The download counts as filed with what is filed; the rest is not filed.

Parameter

FeldWoTypBedeutung
download_id *pathinteger

Antwort 200 ActOut

FeldTypBedeutung
download *QueueItemOutThe download as it stands after the action.

Fehlercodes

  • 401 api_key_missing, api_key_invalid
  • 403 scope_missing
  • 404 download_not_found
  • 409 action_not_allowed, download_not_assignable, download_busy
  • 422 invalid_input
  • 500 internal_error
POST/api/v1/downloads/{download_id}/removeRemove a downloadBedienen

The download client drops the job (SABnzbd with its files, a torrent without). With search_again the release goes on the title's blocklist and the title into the order of the automatic, even with its switch off. Filed files are never touched.

Parameter

FeldWoTypBedeutung
download_id *pathinteger

Antwort 200 ActOut

FeldTypBedeutung
download *QueueItemOutThe download as it stands after the action.

Fehlercodes

  • 401 api_key_missing, api_key_invalid
  • 403 scope_missing
  • 404 download_not_found
  • 409 action_not_allowed, download_finished
  • 422 invalid_input
  • 500 internal_error
POST/api/v1/downloads/{download_id}/retryTry a download againBedienen

A problem the client reported goes back to the client, any other to filing away.

Parameter

FeldWoTypBedeutung
download_id *pathinteger

Antwort 200 ActOut

FeldTypBedeutung
download *QueueItemOutThe download as it stands after the action.

Fehlercodes

  • 401 api_key_missing, api_key_invalid
  • 403 scope_missing
  • 404 download_not_found
  • 409 action_not_allowed, download_not_retryable
  • 422 invalid_input
  • 500 internal_error
POST/api/v1/downloads/{download_id}/searchSearch the title of a download againBedienen

The title goes into the order of the automatic, even with its switch off, within the indexers' budget. A failed download is taken off the problems with it.

Parameter

FeldWoTypBedeutung
download_id *pathinteger

Antwort 200 ActOut

FeldTypBedeutung
download *QueueItemOutThe download as it stands after the action.

Fehlercodes

  • 401 api_key_missing, api_key_invalid
  • 403 scope_missing
  • 404 download_not_found
  • 409 action_not_allowed
  • 422 invalid_input
  • 500 internal_error
GET/api/v1/foreign-jobsJobs in nexcrate's category that no download followsLesen

Put there by hand, by another program, or handed over without an answer and never matched; read from the clients once a minute. nexcrate never imports them by itself. The owner assigns one to a movie in the interface; a program can remove one. Since 22.09.2026.

Antwort 200 ForeignJobsV1Out

FeldTypBedeutung
items *array of ForeignJobV1Out

Fehlercodes

  • 401 api_key_missing, api_key_invalid
  • 403 scope_missing
  • 500 internal_error
POST/api/v1/foreign-jobs/{job_id}/importAssign a foreign job to a title of the library and import itBedienen

As in the interface: the job becomes a download of the version and is filed away when finished. Only titles of the library; a series job is for the episodes its name names. Needs the scope operate. Since 22.09.2026.

Parameter

FeldWoTypBedeutung
job_id *pathinteger

Anfrage ForeignAdoptV1In

FeldTypBedeutung
kind *"movie" | "series" | "album"
ref *stringThe title as everywhere in /api/v1, for example tmdb:603.
version_id *stringThe public id of the version definition.

Antwort 201 ForeignAdoptV1Out

FeldTypBedeutung
download_id *integerThe download the job became; follow it in the queue.

Fehlercodes

  • 401 api_key_missing, api_key_invalid
  • 403 scope_missing
  • 404 not_found, title_not_found
  • 409 foreign_job_failed, foreign_same_release, foreign_no_version, foreign_no_episodes, version_owned_by_source
  • 422 invalid_input, version_unknown, version_kind_mismatch
  • 500 internal_error
POST/api/v1/foreign-jobs/{job_id}/removeRemove a foreign job with its filesBedienen

The job leaves the download client with its files. Needs the scope operate.

Parameter

FeldWoTypBedeutung
job_id *pathinteger

Fehlercodes

  • 401 api_key_missing, api_key_invalid
  • 403 scope_missing
  • 404 not_found
  • 422 invalid_input
  • 500 internal_error
  • 502 client_unreachable
GET/api/v1/problemsDownloads with a problem, and what may be doneLesen

The downloads of the queue with a problem or a hint, those that need somebody first. Each problem names its allowed actions and which of them an automatic may take without a human.

Parameter

FeldWoTypBedeutung
kindquerystring | null

Antwort 200 QueueOut

FeldTypBedeutung
items *array of QueueItemOutNewest first.

Fehlercodes

  • 401 api_key_missing, api_key_invalid
  • 403 scope_missing
  • 422 kind_unsupported, invalid_input
  • 500 internal_error
GET/api/v1/queueWhat is loading, stuck or failedLesen

Every download that is not finished, one entry per download with its episodes and one state: running, stuck, and failed ones that wait for the owner. Progress and remaining time are only here, never events.

Parameter

FeldWoTypBedeutung
kindquerystring | null

Antwort 200 QueueOut

FeldTypBedeutung
items *array of QueueItemOutNewest first.

Fehlercodes

  • 401 api_key_missing, api_key_invalid
  • 403 scope_missing
  • 422 kind_unsupported, invalid_input
  • 500 internal_error
GET/api/v1/queue/{download_id}One downloadLesen

A download as the queue lists it, also after it finished.

Parameter

FeldWoTypBedeutung
download_id *pathinteger

Fehlercodes

  • 401 api_key_missing, api_key_invalid
  • 403 scope_missing
  • 404 download_not_found
  • 422 invalid_input
  • 500 internal_error
Referenz

Ereignisse

Was passiert ist, als Liste mit Laufnummer oder als Strom. Webhooks schicken dasselbe.

GET/api/v1/eventsWhat happened since a numberLesen

Events after after, oldest first; ask again with next_after. Start with the latest of a first call. Events stay 90 days; a number older than that answers 410 marker_too_old: read the library again. Types: title.added, title.changed, title.removed, version.added, version.removed, download.started, download.state, download.imported, download.failed, download.removed, problem.opened, problem.closed, file.deleted, file.restored, request.made, request.withdrawn, series.season_complete, version_definition.added, version_definition.changed, version_definition.removed, health.changed, source.taken_over, source.takeover_undone.

Parameter

FeldWoTypBedeutung
afterqueryintegerThe next_after of the last answer.
limitqueryinteger

Antwort 200 EventsOut

FeldTypBedeutung
items *array of EventOutOldest first.
next_after *integerAsk with this next.
more *booleanTrue: ask again at once.
latest *integerThe highest number given so far.

Fehlercodes

  • 401 api_key_missing, api_key_invalid
  • 403 scope_missing
  • 410 marker_too_old
  • 422 invalid_input
  • 500 internal_error
GET/api/v1/events/streamThe events as a streamLesen

The same events as Server-Sent Events: id is the number, event the type, data the event as JSON; a comment every 15 seconds keeps proxies from closing. One way only: nexcrate never needs to reach the program. After a break reconnect with the header Last-Event-ID or after. A stream ends after an hour. At most 5 open streams per key (too_many_streams).

Parameter

FeldWoTypBedeutung
afterqueryinteger | nullThe number to follow; the latest when left out.
Last-Event-IDheaderstring | null

Fehlercodes

  • 401 api_key_missing, api_key_invalid
  • 403 scope_missing
  • 410 marker_too_old
  • 422 invalid_input
  • 429 too_many_streams
  • 500 internal_error
Referenz

Kalender und Wertungen

Was wann erscheint, und die Wertungen von IMDb, Rotten Tomatoes und Metacritic.

GET/api/v1/calendarWhat comes out in a span of daysLesen

Movies with their cinema, digital and disc dates, episodes on the day they air, at most 100 days at once. A movie's date is the one of the region (the one set in nexcrate, or region); without a date there, the earliest anywhere, and country names it.

Parameter

FeldWoTypBedeutung
from *querystringYYYY-MM-DD.
to *querystringYYYY-MM-DD.
kindquerystring | null
regionquerystring | nullISO 3166-1; left out, the one set.
monitoredquerybooleanOnly what a version watches.
missingquerybooleanOnly what has no file yet.

Antwort 200 CalendarOut

FeldTypBedeutung
from *string
to *string
region *stringThe region the movie dates come from; empty is the earliest date anywhere.
items *array of CalendarEntryOutBy day.
truncated *booleanThe span held more entries than one answer carries: ask a shorter one.

Fehlercodes

  • 401 api_key_missing, api_key_invalid
  • 403 scope_missing
  • 422 kind_unsupported, invalid_input
  • 500 internal_error
POST/api/v1/ratingsIMDb ratings of many titles at onceLesen

Up to 100 titles, also titles that are in no library, from nexcrate's own copy of IMDb's daily file; Rotten Tomatoes and Metacritic from the 30-day store of OMDb answers. A tmdb: title nexcrate does not have is looked up at TMDB once for its IMDb number (kept 30 days); nothing else leaves. Information courtesy of IMDb (https://www.imdb.com). Used with permission.

Anfrage RatingsIn

FeldTypBedeutung
items *array of RatingItemIn

Antwort 200 RatingsOut

FeldTypBedeutung
items *array of RatingItemOutIn the order asked.
imdb *stringloaded, off (the owner switched it off) or not_loaded (not loaded yet).
attribution *stringShow it where the ratings show.
omdb_attribution *string | nullShow it too when any Rotten Tomatoes or Metacritic value shows; null when none does.

Fehlercodes

  • 401 api_key_missing, api_key_invalid
  • 403 scope_missing
  • 422 invalid_input
  • 500 internal_error
GET/api/v1/ratings/{kind}/{ref}The ratings of one titleLesen

IMDb from nexcrate's copy; with an OMDb key of the owner also Rotten Tomatoes and Metacritic (movies only), kept 30 days and within OMDb's daily limit. Information courtesy of IMDb (https://www.imdb.com). Used with permission.

Parameter

FeldWoTypBedeutung
kind *pathstring
ref *pathstring

Antwort 200 RatingOut

FeldTypBedeutung
kind *string
ref *string
imdb_ref *string | null
imdb *ImdbRatingOut | null
rotten_tomatoes *integer | nullThe Tomatometer in percent.
metacritic *integer | nullThe Metascore, 0 to 100.
sources *object of stringimdb: loaded, off or not_loaded. omdb: ok, not_found, no_key, key_invalid, limit (the day's requests are used up), failed, or not_for_kind (OMDb has no such values for series).
attribution *array of string

Fehlercodes

  • 401 api_key_missing, api_key_invalid
  • 403 scope_missing
  • 404 imdb_unknown
  • 409 ref_ambiguous
  • 422 kind_unsupported, ref_invalid, ref_source_unknown, invalid_input
  • 500 internal_error
Referenz

Papierkorb

Was ersetzt oder gelöscht wurde und noch zurückgeholt werden kann.

GET/api/v1/recycle-binRead the recycle binLesen

What was deleted, by whom, and whether it can come back: movies, series and albums, one entry per file.

Parameter

FeldWoTypBedeutung
kindquerystring | null

Antwort 200 RecycleBinOut

FeldTypBedeutung
items *array of RecycleEntryOutNewest first.

Fehlercodes

  • 401 api_key_missing, api_key_invalid
  • 403 scope_missing
  • 422 kind_unsupported, invalid_input
  • 500 internal_error
POST/api/v1/recycle-bin/{entry_id}/restoreTake a file back out of the recycle binAnfragen

The file goes back where it was and counts again. Refused when something lies there (recycle_target_taken), when the version or episode has another file by now (recycle_slot_taken), when the title or version left the library (recycle_title_gone) or when the file is gone (recycle_file_gone); the file then stays in the bin.

Parameter

FeldWoTypBedeutung
entry_id *pathinteger

Antwort 200 RestoredOut

FeldTypBedeutung
title *TitleOut

Fehlercodes

  • 401 api_key_missing, api_key_invalid
  • 403 scope_missing
  • 404 not_found
  • 409 recycle_target_taken, recycle_slot_taken, recycle_title_gone, recycle_file_gone, version_fed_by_source
  • 422 invalid_input
  • 500 internal_error
Referenz

Koppeln

Ein Programm bittet um einen Schlüssel, der Besitzer bestätigt in nexcrate. Die einzigen Adressen ohne Schlüssel.

POST/api/v1/pairingAsk to be connectedohne Schlüssel

Needs no key. nexcrate shows the request with its code to the owner, who confirms it with the scopes of the owner's choice or denies it. Ask GET /api/v1/pairing/{pairing_id} with the secret until it is decided; a request lives 10 minutes, at most 5 wait at once.

Anfrage PairingIn

FeldTypBedeutung
app *stringThe program's name, shown to the owner.
scopes *array of stringread, request, operate; the owner may choose fewer.

Antwort 201 PairingOut

FeldTypBedeutung
pairing_id *string
secret *stringSend it as X-Pairing-Secret when asking how the request stands. Shown once.
code *stringShow it to the owner: nexcrate shows the same.
expires_at *string
poll_seconds *integerAsk again after this many seconds.

Fehlercodes

  • 403 csrf_header_missing
  • 422 invalid_input
  • 429 pairing_limit
  • 500 internal_error
GET/api/v1/pairing/{pairing_id}How a request to be connected standsohne Schlüssel

With the header X-Pairing-Secret. Confirmed, the answer carries the key once; from then on the request is delivered. An unknown request and a wrong secret both answer 404.

Parameter

FeldWoTypBedeutung
pairing_id *pathstring
X-Pairing-Secretheaderstring | null

Antwort 200 PairingStateOut

FeldTypBedeutung
state *stringpending, confirmed (this answer carries the key), delivered, denied or expired.
key *string | nullThe key, exactly once: in the first answer after the owner confirmed.
scopes *array of string | nullWhat the owner granted, with the key.
expires_at *string

Fehlercodes

  • 404 pairing_not_found
  • 422 invalid_input
  • 500 internal_error