docs: bebilderte Anleitung, API-Dokumentation und Screenshots
docs/ANLEITUNG.md führt einmal durch die ganze Anwendung — von der ersten Anmeldung über das tägliche Abhaken bis zu Universen, Statistik und Verwaltung, mit 18 Aufnahmen aus der laufenden Instanz. Die Bilder entstehen mit npm run screenshots: aufgenommen mit doppelter Pixeldichte für scharfe Schrift, abgelegt als WebP in halber Kantenlänge — 13 MB werden so zu 0,6 MB.
This commit is contained in:
+190
@@ -0,0 +1,190 @@
|
||||
# Flimmer — REST-API
|
||||
|
||||
Alles, was die Oberfläche kann, geht auch über die Schnittstelle: Bibliothek
|
||||
lesen und pflegen, Episoden abhaken, suchen, Kalender und Statistik abrufen,
|
||||
Universen verwalten, Daten exportieren.
|
||||
|
||||
Die maschinenlesbare Beschreibung liegt unter
|
||||
`GET /api/v1/openapi.json` (OpenAPI 3.1) — damit lassen sich Clients erzeugen
|
||||
oder die Endpunkte in Insomnia, Bruno oder Postman importieren.
|
||||
|
||||
## Anmeldung
|
||||
|
||||
Jede Anfrage trägt einen persönlichen API-Schlüssel im `Authorization`-Kopf:
|
||||
|
||||
```bash
|
||||
curl -H "Authorization: Bearer flm_a1b2c3d4.xxxxxxxxxxxx" \
|
||||
https://flimmer.example.com/api/v1/me
|
||||
```
|
||||
|
||||
Schlüssel legst du unter **Einstellungen → API-Schlüssel** an. Der Klartext ist
|
||||
**einmalig** sichtbar; danach liegt in der Datenbank nur ein Hash. Ein Schlüssel
|
||||
hat dieselben Rechte wie dein Konto — behandle ihn wie ein Passwort und zieh ihn
|
||||
zurück, sobald du ihn nicht mehr brauchst.
|
||||
|
||||
Aus dem Browser heraus funktioniert stattdessen das Sitzungscookie; dieselben
|
||||
Endpunkte bedienen also Skripte und das eigene Frontend.
|
||||
|
||||
## Antwortformat
|
||||
|
||||
Alle Antworten sind JSON. Zeitangaben in ISO 8601, Laufzeiten in Minuten.
|
||||
Fehler tragen immer ein Feld `error`:
|
||||
|
||||
```json
|
||||
{ "error": "Diesen Eintrag gibt es nicht." }
|
||||
```
|
||||
|
||||
| Status | Bedeutung |
|
||||
|---|---|
|
||||
| 200 | In Ordnung |
|
||||
| 401 | Kein oder ungültiger Schlüssel |
|
||||
| 404 | Nicht vorhanden (oder nicht deins) |
|
||||
| 422 | Anfrage unvollständig — `details` nennt die Felder |
|
||||
| 502 / 503 | TMDB nicht erreichbar bzw. kein Schlüssel hinterlegt |
|
||||
|
||||
## Endpunkte
|
||||
|
||||
### Konto
|
||||
|
||||
```http
|
||||
GET /api/v1/me
|
||||
```
|
||||
|
||||
### Bibliothek
|
||||
|
||||
```http
|
||||
GET /api/v1/bibliothek?status=WATCHING&typ=SERIES&genre=Drama&q=nord&limit=50&offset=0
|
||||
POST /api/v1/bibliothek
|
||||
```
|
||||
|
||||
Filter: `q`, `status`, `typ`, `genre`, `tag`, `dienst`, `limit`, `offset`.
|
||||
Status: `WATCHING`, `PAUSED`, `COMPLETED`, `DROPPED`, `WATCHLIST`.
|
||||
|
||||
Aufnehmen — entweder mit interner Kennung oder direkt mit der TMDB-Kennung:
|
||||
|
||||
```bash
|
||||
curl -X POST -H "Authorization: Bearer $KEY" -H "content-type: application/json" \
|
||||
-d '{"tmdbId": 1396, "type": "SERIES", "status": "WATCHING"}' \
|
||||
https://flimmer.example.com/api/v1/bibliothek
|
||||
```
|
||||
|
||||
```http
|
||||
GET /api/v1/bibliothek/{entryId}
|
||||
PATCH /api/v1/bibliothek/{entryId}
|
||||
DELETE /api/v1/bibliothek/{entryId}
|
||||
```
|
||||
|
||||
`GET` liefert den Eintrag samt `progress` und `nextEpisode`.
|
||||
`PATCH` ändert `status`, `rating` (1–10), `notes`, `whereToWatch`, `favorite`.
|
||||
`DELETE` legt den Eintrag in den Papierkorb — dort bleibt er 30 Tage.
|
||||
|
||||
### Sichtungen
|
||||
|
||||
```http
|
||||
GET /api/v1/bibliothek/{entryId}/sichtungen
|
||||
POST /api/v1/bibliothek/{entryId}/sichtungen
|
||||
DELETE /api/v1/bibliothek/{entryId}/sichtungen
|
||||
```
|
||||
|
||||
`POST` kennt fünf Formen:
|
||||
|
||||
| Rumpf | Wirkung |
|
||||
|---|---|
|
||||
| `{"action":"next"}` | Die nächste offene Episode abhaken |
|
||||
| `{"action":"movie"}` | Einen Film als gesehen markieren |
|
||||
| `{"action":"episodes","episodeIds":["…"]}` | Eine Auswahl abhaken |
|
||||
| `{"action":"season","seasonId":"…"}` | Eine ganze Staffel |
|
||||
| `{"action":"upTo","episodeId":"…"}` | Alles bis einschließlich dieser Episode |
|
||||
|
||||
Die Antwort trägt `watchIds` — damit lässt sich genau diese Aktion zurücknehmen:
|
||||
|
||||
```bash
|
||||
# Nächste Episode abhaken
|
||||
IDS=$(curl -s -X POST -H "Authorization: Bearer $KEY" -H "content-type: application/json" \
|
||||
-d '{"action":"next"}' \
|
||||
https://flimmer.example.com/api/v1/bibliothek/$ENTRY/sichtungen | jq -c .watchIds)
|
||||
|
||||
# … und wieder zurücknehmen
|
||||
curl -X DELETE -H "Authorization: Bearer $KEY" -H "content-type: application/json" \
|
||||
-d "{\"watchIds\": $IDS}" \
|
||||
https://flimmer.example.com/api/v1/bibliothek/$ENTRY/sichtungen
|
||||
```
|
||||
|
||||
Alternativ nimmt `DELETE` auch `{"episodeIds":["…"]}` — dann verschwindet die
|
||||
Markierung dieser Episoden im aktuellen Durchlauf.
|
||||
|
||||
### Suche
|
||||
|
||||
```http
|
||||
GET /api/v1/suche?q=nordlicht&typ=serie
|
||||
```
|
||||
|
||||
Durchsucht TMDB. Die Treffer tragen `tmdbId` und `type` — direkt verwendbar für
|
||||
`POST /api/v1/bibliothek`. Ohne hinterlegten TMDB-Schlüssel antwortet der
|
||||
Endpunkt mit 503.
|
||||
|
||||
### Kalender
|
||||
|
||||
```http
|
||||
GET /api/v1/kalender?von=2026-09-01&bis=2026-09-30
|
||||
```
|
||||
|
||||
Kommende Episoden der getrackten Serien. Ohne Zeitraum: die nächsten 30 Tage.
|
||||
|
||||
### Statistik
|
||||
|
||||
```http
|
||||
GET /api/v1/statistik?jahr=2026
|
||||
```
|
||||
|
||||
Liefert `totals`, `monthly`, `providers`, `genres` und `yearReview` auf einmal.
|
||||
|
||||
### Universen
|
||||
|
||||
```http
|
||||
GET /api/v1/universen
|
||||
POST /api/v1/universen
|
||||
GET /api/v1/universen/{id}?reihenfolge={orderId}
|
||||
POST /api/v1/universen/{id}
|
||||
```
|
||||
|
||||
`GET /api/v1/universen/{id}` gibt die Einträge in der gewählten Reihenfolge
|
||||
zurück, dazu `progress` und `nextUp`. Ohne `reihenfolge` gilt die
|
||||
Erscheinungsreihenfolge.
|
||||
|
||||
### Export
|
||||
|
||||
```http
|
||||
GET /api/v1/export?format=json
|
||||
GET /api/v1/export?format=csv
|
||||
```
|
||||
|
||||
JSON enthält zusätzlich alle Sichtungen und Universen.
|
||||
|
||||
## Beispiel: Serien mit offener Episode auflisten
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
KEY="flm_…"
|
||||
HOST="https://flimmer.example.com"
|
||||
|
||||
curl -s -H "Authorization: Bearer $KEY" \
|
||||
"$HOST/api/v1/bibliothek?status=WATCHING&typ=SERIES" \
|
||||
| jq -r '.items[] | "\(.title): \(.watched)/\(.total)"'
|
||||
```
|
||||
|
||||
## Grenzen
|
||||
|
||||
Es gibt bewusst keine Ratenbegrenzung: Flimmer läuft auf deinem eigenen Server,
|
||||
und ein Limit gegen dich selbst hilft niemandem. Wer die Instanz öffentlich
|
||||
erreichbar macht, setzt so etwas besser im Reverse Proxy.
|
||||
|
||||
Der Abgleich mit TMDB lässt sich über einen eigenen Endpunkt anstoßen — der
|
||||
nimmt allerdings das Cron-Geheimnis, nicht einen API-Schlüssel:
|
||||
|
||||
```bash
|
||||
curl -X POST -H "Authorization: Bearer $CRON_SECRET" \
|
||||
https://flimmer.example.com/api/cron/sync
|
||||
```
|
||||
Reference in New Issue
Block a user