Version 0.1.0. This is the human-readable reference. Machine-readable equivalents are served live by the running service and shipped in the package:
GET /openapi.json — OpenAPI 3.1 spec (source: api/openapi.json).GET /llms.txt — a compact, agent-friendly summary following the
llmstxt.org convention (source: api/llms.txt).GET /docs — this reference rendered as an interactive page (Redoc)./api/v1. All /api/v1/* routes require authentication.Authorization: Bearer <KEY>.POST /ui/login) and rides a cookie session
thereafter (credentials: include).GET /healthz, GET /readyz, GET /openapi.json,
GET /llms.txt, GET /docs, and the static UI.Each API key carries grants: a set of project names it may access (or "*" for
all) plus an admin flag.
| Route class | Requirement | On failure |
|---|---|---|
/api/v1/projects/{project}/… (collections, documents, vectors, search, project stats) |
key is admin, or holds "*", or lists {project} |
403 |
POST/DELETE /api/v1/projects, all /api/v1/keys, GET /api/v1/stats |
admin |
403 |
GET /api/v1/projects |
any valid key (result filtered to granted projects) | — |
any /api/v1/* with a missing/unknown key |
— | 401 |
On first run with no keys, the service generates one admin key
(projects:["*"], admin:true) and logs it once.
All errors return JSON {"error": {"code": "<slug>", "message": "<text>"}} with a
standard HTTP status: 400 malformed request, 401 unauthenticated, 403
forbidden (valid key lacking the grant), 404 not found, 422 validation
(bad body, dimension mismatch, reserved name), 503 database/embedding
unavailable, 500 unexpected.
A project is an isolated namespace (collections in one project are invisible to
others). default always exists and cannot be deleted.
| Method | Path | Auth | Body / notes |
|---|---|---|---|
GET |
/api/v1/projects |
any key | → {"projects": ["default", ...]} (only granted projects) |
POST |
/api/v1/projects |
admin | {"name":"acme"} — name ^[a-zA-Z_][a-zA-Z0-9_-]{0,62}$ → 201 {"name":"acme"} |
GET |
/api/v1/projects/{project} |
project access | → {"name","collections"} |
DELETE |
/api/v1/projects/{project} |
admin | drops the project + its collections (not default) |
curl -s -X POST $BASE/api/v1/projects -H "Authorization: Bearer $KEY" \
-H 'Content-Type: application/json' -d '{"name":"acme"}'
Keys are referenced by a stable, non-secret id (from the list); the secret
value is only shown once, at creation.
| Method | Path | Body / notes |
|---|---|---|
GET |
/api/v1/keys |
→ {"keys":[{id,label,projects,admin,created_at,key_prefix}]} (secret masked) |
POST |
/api/v1/keys |
{"label":"n8n","projects":["acme"],"admin":false} → 201 with the full key once |
PATCH |
/api/v1/keys/{id} |
{label?,projects?,admin?} — update grants |
DELETE |
/api/v1/keys/{id} |
revoke (rejected with 422 if it's the last admin) |
# create a scoped key for n8n, limited to project "acme"
curl -s -X POST $BASE/api/v1/keys -H "Authorization: Bearer $ADMIN" \
-H 'Content-Type: application/json' \
-d '{"label":"n8n-acme","projects":["acme"],"admin":false}'
# → {"id":"...","label":"n8n-acme","projects":["acme"],"admin":false,"key":"<shown once>"}
Collections are admin-managed: create one before writing. kind is json
(documents) or vector (RAG; fixed vector_dimension). Names may not start with
_ or the reserved vectorapi_ prefix.
| Method | Path | Body / notes |
|---|---|---|
POST |
/api/v1/projects/{p}/collections |
{"name","kind":"json"\|"vector","vector_dimension"?,"embedding_model"?} |
GET |
/api/v1/projects/{p}/collections |
→ {"collections":[{name,kind,vector_dimension,embedding_model,document_count,size_bytes}]} |
GET |
/api/v1/projects/{p}/collections/{name} |
one collection's info |
DELETE |
/api/v1/projects/{p}/collections/{name} |
drop it |
embedding_model (vector collections) is the OpenAI model used when storing/
searching by text; its output dimension must equal vector_dimension
(text-embedding-3-small = 1536, text-embedding-3-large = 3072).
curl -s -X POST $BASE/api/v1/projects/acme/collections -H "Authorization: Bearer $KEY" \
-H 'Content-Type: application/json' \
-d '{"name":"memories","kind":"vector","vector_dimension":1536,"embedding_model":"text-embedding-3-small"}'
Under /api/v1/projects/{p}/collections/{name}/documents.
| Method | Path | Body / notes |
|---|---|---|
POST |
.../documents |
{"id"?,"data":{...}} (or the raw doc) → 201 {"id"} |
GET |
.../documents/{id} |
the document |
GET |
.../documents |
find — query params below → {"documents":[...],"count"} |
PATCH |
.../documents/{id} |
merge fields → {"id","version"} |
PUT |
.../documents/{id} |
replace the whole document |
DELETE |
.../documents/{id} |
delete |
Find query params: filter (repeatable, field:op:value, AND-combined),
limit, offset, sort, desc (true/false). Operators (op): eq, ne,
gt, gte, lt, lte, in, contains, exists, regex, search. The value
is parsed as JSON when possible, else as a string.
curl -s -X POST $BASE/api/v1/projects/acme/collections/users/documents -H "Authorization: Bearer $KEY" \
-H 'Content-Type: application/json' -d '{"data":{"name":"Alice","age":30}}'
curl -s "$BASE/api/v1/projects/acme/collections/users/documents?filter=age:gte:18&filter=name:search:Ali&limit=20&sort=age&desc=true" \
-H "Authorization: Bearer $KEY"
Under /api/v1/projects/{p}/collections/{name} (vector collections only).
| Method | Path | Body |
|---|---|---|
POST |
.../vectors |
{"id"?,"text"?,"vector"?,"metadata"?} — provide vector to store as-is, or text to embed (OpenAI) → 201 {"id"} |
POST |
.../search |
{"query_text"?\|"query_vector"?,"top_k":5,"min_score":0.0} → {"results":[{id,score,data}]} ordered by descending cosine similarity |
A provided/generated vector's length must equal the collection's
vector_dimension (else 422). Storing by text or searching by query_text
requires OPENAI_API_KEY to be configured (else 422/503).
curl -s -X POST $BASE/api/v1/projects/acme/collections/memories/vectors -H "Authorization: Bearer $KEY" \
-H 'Content-Type: application/json' -d '{"text":"user prefers dark mode","metadata":{"src":"n8n"}}'
curl -s -X POST $BASE/api/v1/projects/acme/collections/memories/search -H "Authorization: Bearer $KEY" \
-H 'Content-Type: application/json' -d '{"query_text":"dark mode","top_k":5,"min_score":0.7}'
| Method | Path | Auth | Returns |
|---|---|---|---|
GET |
/api/v1/projects/{p}/stats |
project access | {project, collections, documents} |
GET |
/api/v1/stats |
admin | server-wide: documents, collections, memory, pressure level, project count |
GET |
/healthz |
public | {"status":"ok"} (liveness) |
GET |
/readyz |
public | {"ready":bool} — 200 if the database is reachable, else 503 |
| Method | Path | Body / notes |
|---|---|---|
POST |
/ui/login |
{"key":"<API key>"} → sets an HttpOnly svapi_session cookie; body {ok,admin,projects} |
POST |
/ui/logout |
clears the session cookie |
Authorization: Bearer <key> header.vector collection with the embedding model matching your dimension, POST .../vectors with text to ingest, and POST .../search with query_text to retrieve context for the LLM node.json collection with POST .../documents (store) and GET .../documents?filter=... (query).