dorfteich/docs/manual/api-guide.md
Claude Fable 5 baebd79cc8
All checks were successful
CD / Build and push images (push) Successful in 1m10s
CD / Deploy to Test (push) Successful in 10s
CD / Smoke tests against Test (push) Successful in 1m14s
CD / Promote to Int (push) Successful in 11s
CI / Lint, typecheck, test (push) Successful in 4m6s
CI / Build container images (push) Has been skipped
CI / Auth e2e pack (push) Successful in 5m35s
CI / Import/export fidelity gate (push) Successful in 48s
German translations of the seven user-facing docs under docs/de/
Mirrors the English tree (docs/de/{features.md,manual/*,developer/
extending.md}) so relative links between translated guides resolve
within the German set; links into untranslated areas (self-hosting,
architecture, deploy) point at the English files and say so. Every
quoted UI label matches the actual German interface strings. Each
pair of files cross-links the other language; English stays
authoritative when the two diverge.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EwZ4jR4KFAPvpjWevfUGX1
2026-07-12 19:28:50 +02:00

4.7 KiB

API guide

Deutsche Fassung: docs/de/manual/api-guide.md

How to talk to Dorfteich from scripts and integrations. The public REST API lives at /api/public/v1; its machine-readable description is served at /api/public/v1/openapi.json.

Switching it on

The API is off by default, twice:

  1. A site admin enables the instance switch (Admin → Settings → Public API).
  2. Each pond that should be reachable opts in (pond settings → "Expose this pond through the public API").

Anything not enabled answers 404 — indistinguishable from an instance without the feature.

Personal access tokens

Create tokens under Settings → API tokens: a name, a scope (read or read+write), an optional expiry date, and optionally a restriction to selected ponds. The secret (dt_pat_…) is shown once — copy it immediately. Tokens are revocable and show their last use.

A token acts as you: it can read and write exactly what you can, narrowed by its scope and pond restriction — never more. Token management itself always requires the browser session; a leaked token cannot mint new tokens.

Authenticate with a bearer header:

curl -H "Authorization: Bearer dt_pat_..." \
  https://wiki.example.com/api/public/v1/me

GET /me is the smoke test — it returns your user, the token scope, and any pond restriction.

Reading

# The ponds this token can reach
curl -H "$AUTH" https://wiki.example.com/api/public/v1/ponds

# Pages of a pond: slug, title, labels, timestamps
curl -H "$AUTH" https://wiki.example.com/api/public/v1/ponds/team/pages

# One page — Markdown source AND rendered, sanitized HTML
curl -H "$AUTH" https://wiki.example.com/api/public/v1/ponds/team/pages/meeting-notes

# Full-text search (optionally ?pond=<slug>&label=<labelId>)
curl -H "$AUTH" "https://wiki.example.com/api/public/v1/search?q=seerose"

# The whole pond as a Markdown ZIP
curl -H "$AUTH" -o team.zip \
  https://wiki.example.com/api/public/v1/ponds/team/export/markdown

Search snippets mark hits with **…**; results carry pond and page slugs for follow-up calls.

Writing (requires the write scope)

# Create a page from Markdown
curl -H "$AUTH" -H 'Content-Type: application/json' \
  -d '{"title": "Meeting notes", "markdown": "# Agenda\n\n- Ducks\n"}' \
  https://wiki.example.com/api/public/v1/ponds/team/pages

# Rename and/or REPLACE the content
curl -X PATCH -H "$AUTH" -H 'Content-Type: application/json' \
  -d '{"markdown": "New content."}' \
  https://wiki.example.com/api/public/v1/ponds/team/pages/meeting-notes

# Move a page to the trash
curl -X DELETE -H "$AUTH" \
  https://wiki.example.com/api/public/v1/ponds/team/pages/meeting-notes

A content PATCH replaces the whole page. It is applied through the live collaborative document: anyone editing the page at that moment sees the change appear, nothing forks, and the previous state remains in the version history as a restorable snapshot (the update itself shows up as a version named "API update").

Labels

GET    /ponds/{pond}/labels                       # the label tree
POST   /ponds/{pond}/labels                       # {name, color?, parentId?}
PATCH  /ponds/{pond}/labels/{labelId}             # rename/recolor/move in one call
DELETE /ponds/{pond}/labels/{labelId}
PUT    /ponds/{pond}/pages/{page}/labels/{labelId}   # assign
DELETE /ponds/{pond}/pages/{page}/labels/{labelId}   # unassign

Label-tree management needs pond-admin rights (like in the app).

Comments

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   # reopen

The pond's comment policy applies exactly as in the app.

Errors, limits, semantics

  • Errors carry the uniform body { "code": "...", "message": "...", "details": {...} }. The code is stable and machine-checkable.
  • 404 vs 403: what you may not read answers 404 (existence stays hidden — including ponds without the API opt-in); a write on something you may read but not change answers 403. A token without the write scope gets 403 scope_required on every write route.
  • Rate limit per token; 429 responses carry a Retry-After header.
  • No cookies are involved anywhere — there is no CSRF surface, and browser sessions cannot call the public API.

Out of scope (for now)

Attachment upload, version endpoints, and webhooks are deliberately not part of v1.

Operator's view of the same feature (switches, security notes): docs/self-hosting/public-api.md.