Skip to content

Latest commit

 

History

History
247 lines (192 loc) · 7.99 KB

API.md

File metadata and controls

247 lines (192 loc) · 7.99 KB

Compendiq API Reference

Compendiq provides a RESTful API built on Fastify 5 with auto-generated interactive documentation.

Interactive API Documentation

The backend serves interactive Swagger UI documentation at:

http://localhost:3051/api/docs

This is the primary API reference. It is auto-generated from route schemas using @fastify/swagger and @fastify/swagger-ui, and is always up to date with the running server.

Note: Swagger UI is only served in non-production environments. It is disabled when NODE_ENV=production to avoid exposing the full API schema.

Authentication

All endpoints except /api/health and /api/auth/* require a valid JWT Bearer token.

Include the token in the Authorization header:

Authorization: Bearer <access-token>

Access tokens are obtained via the login endpoint and have a configurable expiry (default: 1 hour). Use the refresh endpoint to obtain new access tokens without re-authenticating.

API Groups

Prefix Description
GET /api/health Health checks (live, ready, start probes)
POST /api/auth/* Authentication (register, login, refresh, logout)
GET/PUT /api/settings User settings (Confluence URL, PAT, model selection)
GET/PUT/DELETE /api/notion/connection Notion internal integration token (hasToken only; secret never returned)
GET /api/notion/tree Authenticated Notion workspace tree (pages and databases selectable; a database carries recommendedMode table/pages plus rowContent, isWiki, rowCount, columns; Board layouts and other unsupported types carry skipReason; Board cards remain selectable articles)
POST /api/notion/import Start a one-shot import of selected Notion pages and databases as standalone pages (202 { status: 'importing' }; databaseModes picks skip/table/pages per database). Results are not on this response.
GET /api/notion/import/status Background import job (idle / importing / complete with per-item success / skip / fail / already_imported plus importedAs page/article/table / error)
GET/POST/PUT/DELETE /api/pages/* Page CRUD, versions, tags, embeddings, duplicates, export/import
GET /api/spaces Confluence space listing and selection
POST /api/sync Manual sync trigger
POST /api/llm/* LLM operations (improve, generate, summarize, ask, PDF extract)
GET /api/embeddings/status Embedding pipeline status
GET/POST/PUT/DELETE /api/templates/* Knowledge base templates (personal + admin-global)
GET/POST /api/comments/* Page comments
GET /api/analytics/* Content analytics and search analytics
GET/POST /api/verification/* Page verification/review workflow
GET/POST /api/notifications/* User notifications
GET/POST /api/admin/* Admin operations (key rotation, audit log, LLM settings, OIDC, RBAC)

Example Requests

Health Check

curl http://localhost:3051/api/health

Response:

{
  "status": "ok",
  "services": {
    "postgres": true,
    "redis": true,
    "llm": true
  },
  "llmProvider": "OpenAI Prod",
  "version": "0.6.2",
  "uptime": 3600.123
}

/api/health is public (unauthenticated). It reports only coarse status plus the provider name and build version the frontend needs. Internal operational telemetry (per-provider circuit-breaker state, LLM/BullMQ queue metrics) is not exposed here.

Register a User

curl -X POST http://localhost:3051/api/auth/register \
  -H "Content-Type: application/json" \
  -d '{
    "username": "admin",
    "email": "admin@example.com",
    "password": "your-secure-password"
  }'

Response:

{
  "user": {
    "id": "uuid",
    "username": "admin",
    "email": "admin@example.com",
    "role": "admin"
  },
  "accessToken": "eyJhbG...",
  "refreshToken": "eyJhbG..."
}

Login

curl -X POST http://localhost:3051/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "username": "admin",
    "password": "your-secure-password"
  }'

Refresh Token

curl -X POST http://localhost:3051/api/auth/refresh \
  -H "Content-Type: application/json" \
  -d '{
    "refreshToken": "eyJhbG..."
  }'

List Pages

curl http://localhost:3051/api/pages \
  -H "Authorization: Bearer <access-token>"

Get a Page

curl http://localhost:3051/api/pages/<page-id> \
  -H "Authorization: Bearer <access-token>"

Article Connections

GET /api/pages/:id/connections returns the article's linked, section, and related groups. IDs on this endpoint are numeric pages.id values, serialized as strings. Each item contains pageId, title, and a reasons array:

Persisted type Evidence on the response
explicit_link direction: incoming or outgoing, verified against the current link content
parent_child direction: parent or child, verified against the current hierarchy
embedding_similarity The persisted numeric score
label_overlap Actual shared labels and the persisted numeric score

Related recommendations contain at most five unique targets, ranked by their highest persisted evidence score, then numeric page ID. Reciprocal similarity rows contribute one target with the maximum score. Direct and hierarchy targets are not repeated as semantic recommendations. An empty response contains three empty arrays; unavailable source pages return 404. Source and target visibility checks precede recommendation ranking.

Deterministic relationship materialization is independent of embeddings. Page mutations invalidate deterministic evidence in the database; the authorized Connections and focused-local-graph read paths settle pending materialization through the shared engine before returning results. Unchanged reads do not rebuild the corpus, and failures are reported rather than converted to empty groups. Semantic scores are not rewritten by deterministic-only work.

POST /api/pages/:id/connections/events collects authenticated panel usage:

{"event":"impression","visitId":"f72f706e-a3b4-46cb-91f0-926558a03d68"}

The other event bodies are {"event":"graph_launch","visitId":"<uuid>"} and {"event":"connection_click","visitId":"<uuid>","targetPageId":"42","group":"related"}. The group is linked, section, or related. Requests use the shared strict ConnectionEventSchema; successful collection returns {"recorded":true}. Never send titles, labels, relationship explanations, scores, or article bodies as analytics metadata. See the administrator guide for impression semantics and the four-week adoption review.

Search Pages

curl "http://localhost:3051/api/search?q=deployment&mode=hybrid" \
  -H "Authorization: Bearer <access-token>"

Every search item includes source: "standalone" | "confluence", taken from the current page record in every search mode and fallback path. A named spaceKey or historical confluenceId does not determine provenance.

Readiness Probe (for Kubernetes / Docker)

curl http://localhost:3051/api/health/ready

Response:

{
  "status": "ok",
  "services": {
    "postgres": true,
    "redis": true
  },
  "version": "0.6.2",
  "uptime": 3600.123
}

Rate Limiting

The API enforces rate limiting:

  • Global: 300 requests per minute per IP (default; configurable by admins)
  • Admin endpoints: stricter limits
  • LLM endpoints: stricter limits (due to resource intensity)

Exceeding the rate limit returns 429 Too Many Requests.

Error Responses

Errors follow a consistent format:

{
  "statusCode": 400,
  "error": "Bad Request",
  "message": "Description of what went wrong"
}

Common status codes:

Code Meaning
400 Bad Request -- invalid input
401 Unauthorized -- missing or invalid token
403 Forbidden -- insufficient permissions
404 Not Found
429 Too Many Requests -- rate limited
500 Internal Server Error
503 Service Unavailable -- dependency down