dorfteich/docs/de/manual/api-guide.md
Claude Fable 5 89ffbc0e4d #147: Eigene Identität in der API klar dokumentiert
GET /api/public/v1/me existiert bereits — OpenAPI-Summary nennt jetzt
ausdrücklich die User-ID, api-guide (en+de) ebenso. MCP war bereits
paritätisch (list_ponds + Token-Identität); kein neuer Endpoint nötig.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0155v2aT8AG1kZDQEZiCLBWC
2026-07-20 00:49:53 +02:00

147 lines
5.5 KiB
Markdown

# API-Handbuch
_Englisches Original: [docs/manual/api-guide.md](../../manual/api-guide.md)_
Wie du aus Skripten und Integrationen mit Dorfteich sprichst. Die
öffentliche REST-API liegt unter `/api/public/v1`; ihre
maschinenlesbare Beschreibung wird unter `/api/public/v1/openapi.json`
ausgeliefert.
## Einschalten
Die API ist **standardmäßig aus**, und zwar doppelt:
1. Ein **Site-Admin** aktiviert den Instanz-Schalter (Admin →
Einstellungen → Öffentliche API).
2. Jeder **Teich**, der erreichbar sein soll, stimmt zu
(Teich-Einstellungen → „Diesen Teich über die öffentliche API
freigeben").
Alles Nicht-Freigeschaltete antwortet mit `404` — ununterscheidbar von
einer Instanz ohne dieses Feature.
## Persönliche API-Tokens
Tokens legst du unter **Einstellungen → API-Tokens** an: ein Name, ein
Scope (`read` oder `read+write`), ein optionales Ablaufdatum und
optional eine Beschränkung auf ausgewählte Teiche. Das Geheimnis
(`dt_pat_…`) wird **ein einziges Mal** angezeigt — sofort kopieren.
Tokens sind widerrufbar und zeigen ihre letzte Verwendung.
Ein Token handelt **als du**: Es kann exakt lesen und schreiben, was du
kannst, eingeengt durch seinen Scope und die Teich-Beschränkung — nie
mehr. Die Token-Verwaltung selbst verlangt immer die Browser-Sitzung;
ein geleaktes Token kann keine neuen Tokens erzeugen.
Authentifiziere dich mit einem Bearer-Header:
```sh
curl -H "Authorization: Bearer dt_pat_..." \
https://wiki.example.com/api/public/v1/me
```
`GET /me` ist der Smoke-Test — er liefert dein Benutzerkonto (samt
deiner User-ID), den Token-Scope und eine etwaige Teich-Beschränkung.
## Lesen
```sh
# Die Teiche, die dieses Token erreicht
curl -H "$AUTH" https://wiki.example.com/api/public/v1/ponds
# Seiten eines Teichs: Slug, Titel, Parent (Seitenbaum-Slug), Labels, Zeitstempel
curl -H "$AUTH" https://wiki.example.com/api/public/v1/ponds/team/pages
# Nur Seiten, die seit einem ISO-8601-Zeitpunkt erstellt/geändert wurden (#148)
curl -H "$AUTH" "https://wiki.example.com/api/public/v1/ponds/team/pages?updatedSince=2026-07-01T00:00:00Z"
# Eine Seite — Markdown-Quelle UND gerendertes, bereinigtes HTML
curl -H "$AUTH" https://wiki.example.com/api/public/v1/ponds/team/pages/meeting-notes
# Volltextsuche (optional ?pond=<slug>&label=<labelId>)
curl -H "$AUTH" "https://wiki.example.com/api/public/v1/search?q=seerose"
# Der ganze Teich als Markdown-ZIP
curl -H "$AUTH" -o team.zip \
https://wiki.example.com/api/public/v1/ponds/team/export/markdown
```
Such-Snippets markieren Treffer mit `**…**`; Ergebnisse tragen Teich-
und Seiten-Slugs für Folgeaufrufe.
## Schreiben (braucht den `write`-Scope)
```sh
# Eine Seite aus Markdown anlegen (optional "parent": ein Seiten-Slug ordnet sie unter)
curl -H "$AUTH" -H 'Content-Type: application/json' \
-d '{"title": "Meeting notes", "markdown": "# Agenda\n\n- Enten\n"}' \
https://wiki.example.com/api/public/v1/ponds/team/pages
# Umbenennen, den Inhalt ERSETZEN und/oder im Seitenbaum verschieben
# ("parent": <slug> ordnet die Seite unter, "parent": null holt sie auf die oberste Ebene)
curl -X PATCH -H "$AUTH" -H 'Content-Type: application/json' \
-d '{"markdown": "Neuer Inhalt."}' \
https://wiki.example.com/api/public/v1/ponds/team/pages/meeting-notes
# Eine Seite in den Papierkorb verschieben
curl -X DELETE -H "$AUTH" \
https://wiki.example.com/api/public/v1/ponds/team/pages/meeting-notes
```
Ein Inhalts-`PATCH` **ersetzt** die ganze Seite. Er wird durch das
lebendige kollaborative Dokument angewandt: Wer die Seite in diesem
Moment bearbeitet, sieht die Änderung erscheinen, nichts spaltet sich
ab, und der vorherige Stand bleibt als wiederherstellbarer
Schnappschuss im Versionsverlauf (das Update selbst erscheint als
Version namens „API update").
## Labels
```sh
GET /ponds/{pond}/labels # der Label-Baum
POST /ponds/{pond}/labels # {name, color?, parentId?}
PATCH /ponds/{pond}/labels/{labelId} # umbenennen/umfärben/verschieben in einem Aufruf
DELETE /ponds/{pond}/labels/{labelId}
PUT /ponds/{pond}/pages/{page}/labels/{labelId} # zuweisen
DELETE /ponds/{pond}/pages/{page}/labels/{labelId} # entfernen
```
Die Verwaltung des Label-Baums braucht Teich-Admin-Rechte (wie in der
App).
## Kommentare
```sh
GET /ponds/{pond}/pages/{page}/comments?filter=all|open|resolved
POST /ponds/{pond}/pages/{page}/comments # {body, parentId?} — Markdown
POST /ponds/{pond}/pages/{page}/comments/{id}/resolve
DELETE /ponds/{pond}/pages/{page}/comments/{id}/resolve # wieder öffnen
```
Die Kommentar-Richtlinie des Teichs gilt exakt wie in der App.
## Fehler, Limits, Semantik
- Fehler tragen den einheitlichen Body `{ "code": "...", "message":
"...", "details": {...} }`. Der `code` ist stabil und maschinell
prüfbar.
- **404 vs. 403**: Was du nicht _lesen_ darfst, antwortet 404 (die
Existenz bleibt verborgen — auch Teiche ohne API-Freigabe); ein
Schreibzugriff auf etwas, das du lesen, aber nicht ändern darfst,
antwortet 403. Ein Token ohne `write`-Scope bekommt auf jeder
Schreibroute `403 scope_required`.
- **Rate-Limit** pro Token; `429`-Antworten tragen einen
`Retry-After`-Header.
- Nirgendwo sind Cookies im Spiel — es gibt keine CSRF-Angriffsfläche,
und Browser-Sitzungen können die öffentliche API nicht aufrufen.
## (Noch) außerhalb des Umfangs
Anhang-Upload, Versions-Endpoints und Webhooks sind bewusst nicht Teil
von v1.
_Die Betreiber-Sicht auf dasselbe Feature (Schalter,
Sicherheitshinweise):
[`docs/self-hosting/public-api.md`](../../self-hosting/public-api.md)
(englisch)._