Files
ledgerdock/doc/api-contract.md

164 lines
6.1 KiB
Markdown

# API Contract
Base URL prefix: `/api/v1`
Primary implementation modules:
- `backend/app/api/router.py`
- `backend/app/api/routes_health.py`
- `backend/app/api/routes_documents.py`
- `backend/app/api/routes_search.py`
- `backend/app/api/routes_processing_logs.py`
- `backend/app/api/routes_settings.py`
## Authentication And Authorization
- Protected endpoints require `Authorization: Bearer <token>` in production.
- Development deployments can allow tokenless user-role access for `documents/*` and `search/*` when `ALLOW_DEVELOPMENT_ANONYMOUS_USER_ACCESS=true`.
- `ADMIN_API_TOKEN` is required for all privileged access and acts as fail-closed root credential.
- `USER_API_TOKEN` is optional and, when configured, grants access to document endpoints only.
- Authorization matrix:
- `documents/*`: `admin` or `user`
- `search/*`: `admin` or `user`
- `settings/*`: `admin` only
- `processing/logs/*`: `admin` only
## Health
- `GET /health`
- Purpose: liveness check
- Response: `{ "status": "ok" }`
## Documents
- Access: admin or user token required (production)
- Access: admin or user token, or development tokenless user fallback when enabled
### Collection and metadata helpers
- `GET /documents`
- Query: `offset`, `limit`, `include_trashed`, `only_trashed`, `path_prefix`, `path_filter`, `tag_filter`, `type_filter`, `processed_from`, `processed_to`
- Response model: `DocumentsListResponse`
- `GET /documents/tags`
- Query: `include_trashed`
- Response: `{ "tags": string[] }`
- `GET /documents/paths`
- Query: `include_trashed`
- Response: `{ "paths": string[] }`
- `GET /documents/types`
- Query: `include_trashed`
- Response: `{ "types": string[] }`
- `POST /documents/content-md/export`
- Body model: `ContentExportRequest`
- Response: ZIP stream containing one markdown file per matched document
### Per-document operations
- `GET /documents/{document_id}`
- Response model: `DocumentDetailResponse`
- `GET /documents/{document_id}/download`
- Response: original file bytes
- `GET /documents/{document_id}/preview`
- Response: inline preview stream only for safe MIME types
- Behavior: script-capable MIME types are forced to attachment responses with `X-Content-Type-Options: nosniff`
- `GET /documents/{document_id}/thumbnail`
- Response: generated thumbnail image when available
- `GET /documents/{document_id}/content-md`
- Response: extracted markdown content for one document
- `PATCH /documents/{document_id}`
- Body model: `DocumentUpdateRequest`
- Response model: `DocumentResponse`
- `POST /documents/{document_id}/trash`
- Response model: `DocumentResponse`
- `POST /documents/{document_id}/restore`
- Response model: `DocumentResponse`
- `DELETE /documents/{document_id}`
- Behavior: permanent delete, requires document to be trashed first
- Response: deletion counters
- `POST /documents/{document_id}/reprocess`
- Response model: `DocumentResponse`
- Behavior: requeues asynchronous processing task
### Upload
- `POST /documents/upload`
- Multipart form fields:
- `files[]` (required)
- `relative_paths[]` (optional)
- `logical_path` (optional, defaults to `Inbox`)
- `tags` (optional CSV)
- `conflict_mode` (`ask`, `replace`, `duplicate`)
- Response model: `UploadResponse`
- Behavior:
- `ask`: returns `conflicts` if duplicate checksum is detected
- `replace`: creates new document linked to replaced document id
- `duplicate`: creates additional document record
- upload `POST` request rejected with `411` when `Content-Length` is missing
- `OPTIONS /documents/upload` CORS preflight bypasses upload `Content-Length` enforcement
- request rejected with `413` when file count, per-file size, or total request size exceeds configured limits
## Search
- Access: admin or user token required
- `GET /search`
- Query: `query` (min length 2), `offset`, `limit`, `include_trashed`, `only_trashed`, `path_filter`, `tag_filter`, `type_filter`, `processed_from`, `processed_to`
- Response model: `SearchResponse`
- Behavior: PostgreSQL full-text and metadata ranking
## Processing Logs
- Access: admin token required
- `GET /processing/logs`
- Query: `offset`, `limit`, `document_id`
- Response model: `ProcessingLogListResponse`
- `limit` is capped by runtime configuration
- sensitive fields are redacted in API responses
- `POST /processing/logs/trim`
- Query: optional `keep_document_sessions`, `keep_unbound_entries`
- Behavior: omitted query values fall back to persisted `/settings.processing_log_retention`
- query values are capped by runtime retention limits
- Response: trim counters
- `POST /processing/logs/clear`
- Response: clear counters
## Settings
- Access: admin token required
- `GET /settings`
- Response model: `AppSettingsResponse`
- persisted providers with invalid base URLs are ignored during read sanitization; response falls back to remaining valid providers or secure defaults
- provider API keys are exposed only as `api_key_set` and `api_key_masked`
- `PATCH /settings`
- Body model: `AppSettingsUpdateRequest`
- Response model: `AppSettingsResponse`
- rejects invalid provider base URLs with `400` when scheme, allowlist, or network safety checks fail
- provider API keys are persisted encrypted at rest (`api_key_encrypted`) and plaintext keys are not written to storage
- `POST /settings/reset`
- Response model: `AppSettingsResponse`
- `PATCH /settings/handwriting`
- Body model: `HandwritingSettingsUpdateRequest`
- Response model: `AppSettingsResponse`
- `GET /settings/handwriting`
- Response model: `HandwritingSettingsResponse`
## Schema Families
Document schemas in `backend/app/schemas/documents.py`:
- `DocumentResponse`
- `DocumentDetailResponse`
- `DocumentsListResponse`
- `UploadConflict`
- `UploadResponse`
- `DocumentUpdateRequest`
- `SearchResponse`
- `ContentExportRequest`
Processing log schemas in `backend/app/schemas/processing_logs.py`:
- `ProcessingLogEntryResponse`
- `ProcessingLogListResponse`
Settings schemas in `backend/app/schemas/settings.py`:
- Provider, task, upload-default, display, processing-log retention, predefined paths or tags, handwriting-style, and legacy handwriting models grouped under `AppSettingsResponse` and `AppSettingsUpdateRequest`.