API Reference
-
FastAPI Endpoints
Endpoints for config, indexing, retrieval, graph, models, keywords, reranker, and health.
-
Schema by Pydantic
Request/response models are defined in Pydantic. The frontend imports generated TypeScript types.
-
Secrets Check
Validate configured provider keys via
/api/secrets/check.
Inspect Schemas
Prefer calling /api/config first to align UI interactions with actual server capabilities. All shapes are Pydantic-driven.
HTTP Conventions
- JSON requests/responses
- Errors via standard status codes with
detail - Streaming responses for long operations are
text/event-streamor chunked JSON
The generated API surface is authoritative
The code-generated API surface reference enumerates every route, handler and response model from the code on every docs run — the inventory table below is a reading aid, not the contract.
Model Usage Costs
Reranking and keyword generation may incur API costs depending on selected models. Control via data/models.json and TriBridConfig.
Endpoint Inventory
| Area | Route | Method | Purpose |
|---|---|---|---|
| Config | /api/config | GET | Get full config |
| Config | /api/config | PUT | Replace config |
| Config | /api/config/{section} | PATCH | Sectional patch, e.g., fusion |
| Config | /api/config/reset | POST | Reset to defaults |
| Config | /api/config/readiness | GET | Integration and dependency readiness (rendered on Admin → Dependencies) |
| Secrets | /api/secrets/check | GET | Check provider keys (never returns values) |
| Index | /api/index | POST | Start indexing |
| Index | /api/index/{corpus_id}/status | GET | Per-corpus status |
| Index | /api/index/{corpus_id}/stats | GET | Per-corpus storage breakdown |
| Index | /api/index/{corpus_id}/runs/{run_id} | GET | Read one exact index or schema-proposal run, including its saved accounting |
| Index | /api/index/{corpus_id}/runs/{run_id}/costs/reconcile | POST | Refresh a saved run's native spend from the gateway ledger |
| Index | /api/index/estimate | POST | Best-effort indexing estimate |
| Index | /api/index/{corpus_id}/graph-schema/proposal | GET | Read the saved graph-schema proposal (current / missing / stale / ineligible) for a read-only review restore — never generates, never bills |
| Index | /api/index/vocab-preview | GET | BM25 vocabulary sample |
| Documents | /api/corpora/{corpus_id}/documents/view | GET | Typed document view (text/pdf/rich) with provenance state |
| Documents | /api/corpora/{corpus_id}/documents/page | GET | Server-rendered PDF page PNG (page/thumb, ETag/304) |
| Documents | /api/corpora/{corpus_id}/documents/raw | GET | Original file bytes (inline PDF, otherwise attachment + sandbox) |
| Search | /api/search | POST | Tri-brid retrieval + fusion (+reranker) |
| Answer | /api/answer | POST | Retrieval + LLM answer generation |
| Answer | /api/answer/stream | POST | Stream answer generation |
| Graph | /api/graph/{corpus_id}/entities | GET | List entities (?q=, ?limit=) |
| Graph | /api/graph/{corpus_id}/entity | GET | Entity details (?entity_id=) |
| Graph | /api/graph/{corpus_id}/entity/neighbors | GET | Neighborhood (?entity_id=&max_hops=&limit=) |
| Graph | /api/graph/{corpus_id}/entity/sources | GET | Paged direct entity mentions, generation-scoped (?entity_id=&offset=&run_id=) |
| Graph | /api/graph/{corpus_id}/subgraph | GET | Corpus or search subgraph (?limit=, ?q=) |
| Models | /api/models/by-type/{component} | GET | Models by component GEN/EMB/RERANK |
| Keywords | /api/keywords/generate | POST | Generate discriminative keywords |
| Reranker | /api/reranker/* | mixed | Status / mine / train / evaluate |
| Health | /api/health | GET | Liveness |
| Health | /api/ready | GET | Readiness |
| Metrics | /api/metrics | GET | Prometheus exposition |
| Docker | /api/docker/* | GET/POST | Infra status, logs, restart |
| MCP | /api/mcp/status | GET | MCP inbound transport status |
Credentials never ride these payloads
Config endpoints (GET/PUT/PATCH /api/config*) replace the password inside indexing.postgres_url and the authorization value in tracing.otlp_headers with [redacted], and every run-record route (/api/eval/results*, /api/reranker/train/run*, /api/agent/train/run*, /api/synthetic/run*) redacts the config snapshot it pins. A write that returns the marker keeps the stored credential; a real value rotates it. GET /api/mcp/status additionally reports the advertised url, host_allowed, public_base_url_configured and request_host for the MCP transport. See Security.
Answer and chat fail closed
/api/answer no longer returns a "retrieval-only" answer when generation is unavailable: the non-stream route answers the typed 503 generation_unavailable the chat lane raises, and the stream emits a typed error event before done. A retrieval failure is its own typed 503 (required_retrieval_leg_failed, reranker_failed, or answer_retrieval_failed) — never an answer assembled from the sources without context, and never a bare 500. See Chat models.
Citations you can open
ChunkMatch now carries typed provenance (extraction method; cited pages and normalized regions for Docling PDFs), and ChatResponse carries web_grounding with validated web citations. See Source document viewer and Web search in Chat.
Graph entity ids travel as a query parameter
Code-graph entity ids are corpus-relative paths (server/services/traces.py::TraceStore.add_event) and carry both / and ::. The entity routes therefore take the id as ?entity_id=…, never as a path segment — the old {entity_id:path} routes were greedy and swallowed the /neighbors and /relationships suffixes of their own sibling routes, which made every code entity 404. A missing id is a typed 404 whose detail names the id you looked up. See Graph API.
flowchart TB
CLI["Client"] --> API["FastAPI"]
API --> PC["Postgres Client"]
API --> NC["Neo4j Client"]
API --> CFG["Pydantic Models"]
API --> ML["Model Catalog"]
PC --> DB["PostgreSQL"]
NC --> GDB["Neo4j"] Example: Search Roundtrip (Annotated)
import httpx
base = "http://127.0.0.1:8012/api"
payload = {
"corpus_id": "tribrid", # (1)!
"query": "authentication flow",
"top_k": 10
}
resp = httpx.post(f"{base}/search", json=payload)
resp.raise_for_status()
res = resp.json() # type: SearchResponse (2)!
print(res["fusion_method"], len(res["matches"]))
- Always scope by
corpus_id(legacyrepo_idis accepted) - Response includes
fusion_method,reranker_mode,latency_ms, andmatches
BASE=http://127.0.0.1:8012/api
curl -sS -X POST "$BASE/search" \
-H 'Content-Type: application/json' \
-d '{"corpus_id":"tribrid","query":"authentication flow","top_k":10}' | jq '.fusion_method, .matches | length'
import type { SearchRequest, SearchResponse } from "./web/src/types/generated";
async function run(req: SearchRequest): Promise<SearchResponse> {
const r = await fetch("/api/search", { method: "POST", headers: {"Content-Type":"application/json"}, body: JSON.stringify(req) });
return await r.json(); // (2)!
}
Health and Metrics
import httpx
print(httpx.get("http://127.0.0.1:8012/api/ready").json()) # readiness
print(httpx.get("http://127.0.0.1:8012/api/metrics").text[:300]) # metrics sample
curl -sS http://127.0.0.1:8012/api/health | jq .
curl -sS http://127.0.0.1:8012/api/ready | jq .
curl -sS http://127.0.0.1:8012/api/metrics | head -n 20
await fetch('/api/ready').then(r => r.ok || Promise.reject('Not ready'))
const metrics = await (await fetch('/api/metrics')).text()
console.log(metrics.split('\n').slice(0,5))
Streaming
Endpoints that can stream long-running operations (e.g., evaluation logs, training metrics) use Server-Sent Events or chunked JSON. Use backpressure-aware clients.