dorfteich/docs/manual/api-guide.md
Claude Fable 5 eeb0ef6794
All checks were successful
CD / Build and push images (push) Successful in 1m9s
CD / Deploy to Test (push) Successful in 10s
CD / Smoke tests against Test (push) Successful in 1m10s
CD / Promote to Int (push) Successful in 11s
CI / Lint, typecheck, test (push) Successful in 4m7s
CI / Build container images (push) Has been skipped
CI / Auth e2e pack (push) Successful in 5m34s
CI / Import/export fidelity gate (push) Successful in 47s
Documentation set: features, manuals (user/pond-admin/site-admin), API, MCP, developer guide
Seven audience-targeted documents (English first, German translation to
follow), linked from the README and a new docs/manual/ index:

- docs/features.md — public-facing feature overview: what Dorfteich
  can do and why that matters
- docs/manual/user-guide.md — everyday use: editor, wikilinks, labels,
  search, comments, watches/digests, import/export, settings
- docs/manual/pond-admin-guide.md — pond configuration: members/roles,
  access rules incl. label scoping and public pages, labels, comment
  policy, plugins, API/MCP opt-ins, files, export
- docs/manual/site-admin-guide.md — instance administration: wizard,
  settings, quotas, uploads, API/MCP switches, legal pages, plugins,
  users, and the system panel (jobs/backups/audit/storage)
- docs/manual/api-guide.md — example-driven public-API walkthrough
  (tokens, reading, writing through the collab-safe path, labels,
  comments, error semantics)
- docs/manual/mcp-guide.md — connecting AI assistants: switches, token
  scopes, Claude Code one-liner, mcp-remote bridge, tool table, audit
  and safety properties
- docs/developer/extending.md — plugin development (sandbox contract,
  SDK, block plugins, bundled apps/fullscreen, shipping) and core
  contributions (stack, dev environment, gates, house rules)

README: documentation index, repository-layout rows for docs/manual and
docs/developer, and the stale "architecture phase" status brought up to
reality. All relative links verified.

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

4.6 KiB

API guide

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.