API reference
novamem exposes one HTTP surface that every transport (REST, MCP, dashboard SPA) drives. The OpenAPI document is generated from the Go server's own route table — it is the source of truth, and a CI drift gate fails if the committed copy falls behind it.
Browse it
Two surfaces, one document:
- Interactive reference — this site, rendered from the spec on
main. GET /api-docson any deployment — the same renderer, embedded in the binary and pointed at that server's own/openapi.json. It documents the server in front of you rather than whatever shipped last, and it works with no internet: the bundle is vendored, not fetched from a CDN. Public, like the spec itself.
OpenAPI spec
Machine-readable: docs/api/openapi.json on GitHub, or /openapi.json on a live server.
Regenerating the static spec
openapi.json is the generated artefact, owned by the Go server. To refresh it after adding a route or editing a schema:
cd go && go run ./cmd/gen-contract && go run ./cmd/gen-tool-docsThe contract is authored in api/openapi.yaml and everything else derives from it: this document, the bytes the server embeds and serves, the MCP tool surface, the route list the mux is checked against, and the tool catalogue. CI re-runs both generators and fails on a dirty tree, so an output can never be edited into disagreeing with the source.
Routes by purpose
| Section | Routes | Auth |
|---|---|---|
| Authentication | /api/auth/*, POST /v1/me/tokens | mixed |
| Data plane | /v1/search, /v1/remember, /v1/capture, /v1/recent, /v1/neighbors, /v1/forget, PUT /v1/memories/{id} | user API token |
| Admin & users | /v1/admin/*, /api/auth/admin/* | session admin |
| MCP tools | /mcp | user API token |
Per-user (cookie-auth) variants
The dashboard/session-scoped /v1/me/* routes are now self-service control-plane routes, not data-plane mirrors. They cover:
GET /v1/me/todayGET /v1/me/onboardingGET /v1/me/metricsand/v1/me/metrics/historyGET /v1/me/projects(+ create/delete/members)GET /v1/me/active-project(+ set/clear)GET /v1/me/tokens(+ mint/revoke)
The data plane itself (/v1/search, /v1/remember, /v1/capture, /v1/recent, /v1/neighbors, /v1/forget, PUT /v1/memories/{id}) accepts both nm_… user bearers and valid Better Auth session credentials.
Health
Always public, no auth:
curl https://novamem.example.com/healthReturns { "ok": true } for public liveness. Dependency detail lives behind the admin deep-health and metrics routes.
Versioning
/v1/* is stable. Breaking changes go to /v2/* with /v1/* kept alive for at least one major release. Schema migrations are forward-only — back up Postgres before upgrading in place.
Generating a typed client
The OpenAPI spec is the source of truth — anything that consumes it works:
# OpenAPI Generator (TypeScript, Go, Rust, …)
npx @openapitools/openapi-generator-cli generate \
-i docs/api/openapi.json -g typescript-fetch -o ./client
# orval (TanStack Query / Axios bindings)
npx orval --input docs/api/openapi.json --output ./client/api.tsFor Go, clients/go is a hand-written client with public types — usually preferable to a generated one.
MCP vs HTTP
Most MCP tools map to the same engine operations as HTTP routes. Reach for HTTP when:
- You're scripting against the server from a non-MCP runtime (CI job, cron, custom CLI)
- You need streaming —
/mcpholds a GET stream open; the JSON routes are request/response - You want fine-grained control over headers, retries, timeouts
Reach for MCP when:
- An AI agent is the caller — MCP is the protocol every modern agent host already speaks
- You want the server to ship behaviour rules to the client via the protocol's
instructionsfield