# Public REST API (issue #104) Dorfteich instances can expose a token-authenticated REST API at `/api/public/v1` for scripts and integrations. It is **off by default**, twice: a Site Admin enables the instance switch (_Admin → Settings → Public API_), and every pond that should be reachable opts in separately (_Pond settings → Public API_). Anything not enabled answers 404 — indistinguishable from an instance without the feature. ## Personal access tokens Every user manages their tokens under _Settings → API tokens_: a name, a scope (`read` or `read+write`), an optional expiry, and an optional restriction to selected ponds. The secret (`dt_pat_…`) is shown exactly once and stored hashed; tokens are revocable and show their last use. A token acts **as its user**: the normal permission model — grants, label scopes, the 404-vs-403 policy — applies unchanged. Scope and pond restriction only narrow it further; they never grant anything the user could not do in the app. ## Using the API ```sh curl -H "Authorization: Bearer dt_pat_..." \ https://your-instance.example/api/public/v1/me ``` - The machine-readable description lives at `/api/public/v1/openapi.json` (reachable without a token while the instance switch is on). - Requests are rate-limited per token (HTTP 429 + `Retry-After`). - Errors carry the api's uniform body: `{ code, message, details? }`. - Page content is Markdown in, Markdown + rendered HTML out. A content update (`PATCH …/pages/{slug}` with `markdown`) **replaces** the whole page; it is applied through the collaborative document, so open editors converge live, and the previous state stays in the version history (the change itself appears as a manual version named "API update"). ### Endpoint overview | Area | Endpoints | | -------- | ---------------------------------------------------------------------------------------------------------------------------------- | | Identity | `GET /me` | | Ponds | `GET /ponds`, `GET /ponds/{slug}` | | Pages | `GET/POST /ponds/{slug}/pages`, `GET/PATCH/DELETE /ponds/{slug}/pages/{pageSlug}` | | Search | `GET /search?q=&pond=&label=` | | Export | `GET /ponds/{slug}/export/markdown` (ZIP) | | Labels | `GET/POST /ponds/{slug}/labels`, `PATCH/DELETE /ponds/{slug}/labels/{id}`, `PUT/DELETE /ponds/{slug}/pages/{pageSlug}/labels/{id}` | | Comments | `GET/POST /ponds/{slug}/pages/{pageSlug}/comments`, `POST/DELETE …/comments/{id}/resolve` | Deliberately not in v1 (stage 2): attachment upload, version endpoints, webhooks. ## Security notes - Bearer tokens only — no cookies are involved, so there is no CSRF surface; browser sessions cannot call the public API and tokens cannot manage tokens. - Token creation and revocation are audit-logged, as is every write through the API (action `api.write`, with the token attributed). - Treat a token like a password. Revoke it under _Settings → API tokens_ the moment it may have leaked.